26 #include <Classes.hpp>
27 #include <Controls.hpp>
28 #include <StdCtrls.hpp>
30 #include <Buttons.hpp>
31 #include <ExtCtrls.hpp>
33 #include <Dialogs.hpp>
34 #include <Graphics.hpp>
35 #include <ComCtrls.hpp>
52 #pragma package(smart_init)
71 TTrain::TTrain(
int Caller,
int RearStartElementIn,
int RearStartExitPosIn, AnsiString InputCode,
int StartSpeedIn,
int MassIn,
double MaxRunningSpeedIn,
72 double MaxBrakeRateIn,
double PowerAtRailIn,
TTrainMode TrainModeIn,
TTrainDataEntry *TrainDataEntryPtrIn,
int RepeatNumberIn,
int IncrementalMinutesIn,
73 int IncrementalDigitsIn,
int SignallerMaxSpeedIn) : RearStartElement(RearStartElementIn), RearStartExitPos(RearStartExitPosIn), HeadCode(InputCode),
74 StartSpeed(StartSpeedIn), Mass(MassIn), MaxRunningSpeed(MaxRunningSpeedIn), MaxBrakeRate(MaxBrakeRateIn), PowerAtRail(PowerAtRailIn),
75 TrainMode(TrainModeIn), TrainDataEntryPtr(TrainDataEntryPtrIn), RepeatNumber(RepeatNumberIn), IncrementalMinutes(IncrementalMinutesIn),
76 IncrementalDigits(IncrementalDigitsIn), SignallerMaxSpeed(SignallerMaxSpeedIn)
87 AnsiString(RearStartExitPosIn) +
"," + AnsiString(InputCode) +
"," + AnsiString(StartSpeedIn) +
"," + AnsiString(MassIn) +
"," +
88 AnsiString(TrainModeIn));
134 for(
int x = 0; x < 4; x++)
143 for(
int x = 0; x < 4; x++)
152 for(
int x = 0; x < 4; x++)
157 for(
int x = 0; x < 4; x++)
161 for(
int x = 0; x < 3; x++)
198 for(
int x = 0; x < 4; x++)
256 throw Exception(
"Error in attempting to delete FrontCodePtr");
260 for(
int x = 0; x < 4; x++)
264 throw Exception(
"Error in attempting to delete BackgroundPtr[" + AnsiString(x) +
"]");
269 for(
int x = 0; x < 4; x++)
273 throw Exception(
"Error in attempting to delete HeadCodeGrPtr[" + AnsiString(x) +
"]");
302 int NextElementPosition, NextEntryPos, ElementLength, SpeedLimit;
368 bool TempDerail =
false;
414 else if((NextElementPosition > -1) && (NextEntryPos > -1))
485 throw Exception(
"Error, LeadElement Exit Connection is NotSet");
495 for(
int x = 0; x < 4; x++)
502 for(
int x = 0; x < 4; x++)
763 int LockedVectorNumber;
888 AnsiString ReasonArray[24] = {
"a driver is awaited",
"a guard is awaited",
"of a medical emergency",
"of a technical problem",
"of a security issue",
889 "of a safety issue",
"of a disturbance",
"a train crew member has been taken ill",
"the driver has been taken ill",
"the guard has been taken ill",
890 "a report has been received concerning safety",
"a shoe has been lost under the train",
"of a reported theft",
891 "of an incident involving an animal",
"some luggage has been lost under the train",
"a minor repair is needed",
"a suspicious object has to be dealt with safely",
892 "a door is stuck open",
"additional stock has to be attached",
"a security alert",
"of a train fault",
"of an operating incident",
"safety checks are required",
893 "of a shortage of on train crew"};
900 if(DwellTime < TDateTime(30.0 / 86400))
902 DwellTime = TDateTime(30.0 / 86400);
904 int random = rand() % 10000;
911 NewDelay = 1.5 * log(
float(2000)/random);
918 NewDelay = 3 * log(
float(3000)/random);
925 NewDelay = 6 * log(
float(3500)/random);
933 if(
NewDelay <
double(DwellTime) * 1440)
939 NewDelay -= double(DwellTime) * 1440;
985 int random2 = rand() % 24;
986 AnsiString Reason = ReasonArray[random2];
988 AnsiString(
int(
NewDelay)) +
" minutes");
991 " minutes because " + Reason);
997 " minutes because of a minor problem");
1138 if(BufferLocation ==
"")
1143 if((BufferLocation ==
"") || (BufferLocation != ExpectedLocation))
1205 int NextElementPosition, NextEntryPos;
1229 NextElementPosition = -1;
1232 if((NextElementPosition > -1) && (NextEntryPos > -1))
1350 AnsiString StationName;
1361 throw Exception(
"Error - Stopped at through station but neither lead nor mid elements have a name");
1374 if((NextElementPosition > -1) && (NextEntryPos > -1))
1508 if(TIFEntryPos == 0)
1544 if(NextElementPosition > -1)
1581 AnsiString Loc =
"";
1582 bool LocNamed =
false;
1611 Loc =
"outside railway";
1643 NextElementPosition = -1;
1654 if((NextElementPosition > -1) && (NextEntryPos > -1) && !
SPADFlag)
1672 if((NextElementPosition > -1) && (NextEntryPos > -1))
1710 FirstPair.second).
GetELink() == TempELink))
1715 SecondPair.second).
GetELink() == TempELink))
1729 FirstPair.second).
GetELink() == TempELink))
1734 SecondPair.second).
GetELink() == TempELink))
1748 FirstPair.second).
GetELink() == TempELink))
1753 SecondPair.second).
GetELink() == TempELink))
1783 ContinuationAutoSigEntry.
RouteNumber = RouteNumber;
1786 int NewLastElement = 0, NewLastExitPos = 0;
1804 if(NewLastElement == -1)
1807 throw Exception(
"Error, Connection = -1 in Continuation loop in UpdateTrain");
1810 if(NewLastExitPos == -1)
1812 throw Exception(
"Error, ConnLinkPos = -1 in Continuation loop in UpdateTrain");
1814 LastElement = NewLastElement;
1815 LastExitPos = NewLastExitPos;
1818 if(CumDistance < 1200)
1824 int FirstDistance = 0;
1825 if(CumDistance >= 1200)
1827 FirstDistance = 100;
1831 FirstDistance = 1200 - CumDistance;
1833 if(FirstDistance < 100)
1835 FirstDistance = 100;
1861 if(VectorIT->RouteNumber == RouteNumber)
1908 LockedVectorNumber)))
2067 for(
int x = 0; x < 4; x++)
2074 for(
int x = 0; x < 4; x++)
2100 if((LeadElementTrainID > -1) && (LeadElementTrainID !=
TrainID))
2105 if(OtherTrainEntryPos == -1)
2107 throw Exception(
"Error - OtherTrainEntryPos not set");
2126 int OtherTrainID = -1;
2127 if((MidExitLinkNum == 1) || (MidExitLinkNum == 3) || (MidExitLinkNum == 7) || (MidExitLinkNum == 9))
2218 bool StopRequired =
false;
2231 int NextElementEntryPos = -1;
2232 int NextElementExitPos = -1;
2233 bool TrainOnNextElement =
false;
2234 bool StopSignalAtNextElement =
false;
2235 if(ForwardConnection)
2243 StopSignalAtNextElement = ((NextTrackElement.
Config[NextElementExitPos] ==
Signal) && (NextTrackElement.
Attribute == 0));
2245 if(TrainAtStopLinkPos1 || TrainAtStopLinkPos2 || (ForwardConnection && (TrainOnNextElement || StopSignalAtNextElement)))
2301 throw Exception(
"Error, Straddle shouldn't be LeadMid prior to resetting at exit from UpdateTrain");
2514 if(Code.Length() != 4)
2518 for(
int x = 1; x < 5; x++)
2525 for(
int x = 0; x < 4; x++)
2689 throw Exception(
"Error in GetOffsetValues - Link value wrong");
2702 if((EntryLink == 1) || (EntryLink == 2) || (EntryLink == 4) || (EntryLink == 7))
2717 AnsiString(
VOffset) +
"," + AnsiString(Element) +
"," + AnsiString(EntryPos) +
"," +
HeadCode);
2726 TRect SourceRect, DestRect;
2728 DestRect.init(0, 0, 8, 8);
2731 Graphics::TBitmap *TempGraphic =
new Graphics::TBitmap;
2733 TempGraphic->PixelFormat = pf8bit;
2734 TempGraphic->Width = 16;
2735 TempGraphic->Height = 16;
2741 TempGraphic->Transparent =
true;
2745 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2746 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2752 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2760 else if(TempElement.
SpeedTag == 89)
2764 else if(TempElement.
SpeedTag == 90)
2768 else if(TempElement.
SpeedTag == 91)
2772 else if(TempElement.
SpeedTag == 92)
2776 else if(TempElement.
SpeedTag == 93)
2780 else if(TempElement.
SpeedTag == 94)
2784 else if(TempElement.
SpeedTag == 95)
2788 TempGraphic->Transparent =
true;
2792 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2793 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2795 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2802 for(
int x = 0; x < 40; x++)
2817 TempGraphic->Transparent =
true;
2821 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2822 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2824 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2838 TempGraphic->Transparent =
true;
2842 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2843 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2847 TempGraphic->Canvas->Draw(0, 0, TempElement.
GraphicPtr);
2850 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2855 TempGraphic->Transparent =
true;
2859 int BDVectorPos = -1;
2868 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2873 TempGraphic->Transparent =
true;
2877 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2878 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2880 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2886 TempGraphic->Transparent =
true;
2890 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2891 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2893 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3159 throw Exception(
"Error, same train on two different bridge tracks");
3205 AnsiString(EntryPos) +
"," +
HeadCode);
3222 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in SetTrainElementID");
3241 AnsiString(EntryPos) +
"," +
HeadCode);
3250 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in ResetTrainElementID");
3283 AnsiString(ElementEntryPos) +
"," + AnsiString(
HOffset) +
"," + AnsiString(
VOffset) +
"," + AnsiString(StraddleValue) +
"," +
HeadCode);
3284 int LockedVectorNumber;
3297 TRect SourceRect, DestRect;
3298 DestRect.init(0, 0, 8, 8);
3305 int FirstELink, SecondELink = -1;
3308 if(RoutePair2.first > -1)
3317 if(SecondELink == -1)
3319 throw Exception(
"Error - Second ELink should be set but isn't in PlotAlternativeTrackRouteGraphic [1]");
3324 throw Exception(
"Error - First & Second ELinks have same value in PlotAlternativeTrackRouteGraphic");
3334 Graphics::TBitmap *DestGraphic =
new Graphics::TBitmap;
3335 DestGraphic->PixelFormat = pf8bit;
3336 DestGraphic->Width = 8;
3337 DestGraphic->Height = 8;
3338 DestGraphic->Transparent =
true;
3341 DestGraphic->Canvas->CopyRect(DestRect, RouteElement.
GetRouteEXGraphicPtr()->Canvas, SourceRect);
3350 PrefDirElement, LockedVectorNumber))
3365 if(ElementEntryPos > 1)
3387 AnsiString(EntryPos) +
"," +
HeadCode);
3389 bool WrongRoute =
false;
3415 int LinkNumber = TrackElement.
Link[EntryPos];
3416 if((LinkNumber == 1) || (LinkNumber == 3) || (LinkNumber == 7) || (LinkNumber == 9))
3421 bool LogActionErrorCalled =
false;
3431 LogActionErrorCalled =
true;
3448 else if(LinkNumber == 3)
3456 LogActionErrorCalled =
true;
3473 else if(LinkNumber == 7)
3481 LogActionErrorCalled =
true;
3498 else if(LinkNumber == 9)
3506 LogActionErrorCalled =
true;
3538 else if((RouteElement.
GetELinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3543 else if((RouteElement.
GetELinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3553 else if((RouteElement.
GetXLinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3558 else if((RouteElement.
GetXLinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3567 throw Exception(
"Error, Element in route but no route found in CheckAndCancelRouteForWrongEndEntry");
3588 bool ColourError =
false, ColourError2 =
false;
3593 ColourError2 =
true;
3595 for(
int x = 0; x < 4; x++)
3600 ColourError2 =
true;
3606 "ERROR: Colour depth insufficient to display train colours properly. Please ensure that the 'safe' (web) palette of 256 colours can be displayed");
3610 for(
int x = 0; x < 4; x++)
3697 AnsiString(EntryPos) +
"," +
HeadCode);
3698 int EntryHalfLength, CurrentElementHalfLength, NextElementHalfLength, CumulativeLength = 0, CurrentTrackVectorPosition = TrackVectorPosition;
3699 int DistanceAtHalfBraking, DistanceAtThreeQuarterBraking, ExitPos, NextTrackVectorPosition, NextEntryPos;
3700 bool RedSignalFlag =
false, BuffersFlag =
false, StationFlag =
false, BuffersOrContinuationNowFlag =
false, ContinuationNextFlag =
false,
3701 TrainInFrontInSignallerModeFlag =
false;
3702 double LimitingSpeed, FrontElementMaxSpeed, MaxExitSpeedAtHalfBrakingSquared, MaxExitSpeedAtHalfBraking, NextSpeedLimit, TempBrakeRate;
3703 double ExitSpeedHalfSquared, ExitSpeedFullSquared;
3704 bool SignallerStopRequired =
false;
3715 if(CurrentTrackVectorPosition > -1)
3719 if((EntryPos == 0) || (EntryPos == 2))
3732 else if(EntryPos == 1)
3756 EntryHalfLength = CurrentElementHalfLength;
3761 throw Exception(
"Error - CurrentTrackVectorPosition < 0 in SetTrainMovementValues");
3765 throw Exception(
"Error - HalfLength or SpeedLimit < 0 in SetTrainMovementValues");
3812 FrontElementMaxSpeed = LimitingSpeed;
3847 double ExitSpeedAtMaxBraking;
3852 ExitSpeedAtMaxBraking = 0;
3862 if(ExitSpeedAtMaxBraking > LimitingSpeed)
3864 SpeedToUse = ExitSpeedAtMaxBraking;
3868 SpeedToUse = LimitingSpeed;
3883 RedSignalFlag =
false;
3884 BuffersFlag =
false;
3885 StationFlag =
false;
3886 BuffersOrContinuationNowFlag =
false;
3887 ContinuationNextFlag =
false;
3890 CumulativeLength += (2 * CurrentElementHalfLength);
3893 SignallerStopRequired =
true;
3915 bool StopRequired =
false;
3929 StationFlag =
false;
3935 BuffersOrContinuationNowFlag =
true;
3937 if(!BuffersOrContinuationNowFlag && !BuffersFlag && !StationFlag)
3941 if((EntryPos == 0) || (EntryPos == 2))
3963 if(NextTrackVectorPosition > -1)
3968 if((NextEntryPos == 0) || (NextEntryPos == 2))
3981 else if(NextEntryPos == 1)
3994 if(NextEntryPos > 1)
4008 throw Exception(
"Error - Trying to access NextTrackVectorPosition when none present in SetTrainMovementValues");
4020 RedSignalFlag =
true;
4042 TrainInFrontInSignallerModeFlag =
true;
4066 if(RedSignalFlag || BuffersFlag || StationFlag || TrainInFrontInSignallerModeFlag || SignallerStopRequired ||
StepForwardFlag)
4078 double MaxHalfSpeed;
4082 if(MaxHalfSpeedAtHalfBraking > FrontElementMaxSpeed)
4084 MaxHalfSpeed = FrontElementMaxSpeed;
4088 MaxHalfSpeed = MaxHalfSpeedAtHalfBraking;
4096 bool HalfSpeedLimited =
false;
4100 HalfSpeedLimited =
true;
4130 if(HalfSpeedLimited)
4155 if(SignallerStopRequired)
4171 int TempMaxExitSpeed;
4174 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4176 MaxExitSpeedAtHalfBraking = 0;
4180 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4184 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4186 TempMaxExitSpeed = FrontElementMaxSpeed;
4190 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4202 if(ExitSpeedHalfSquared < 10)
4212 if(ExitSpeedFullSquared < 10)
4284 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4285 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4309 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4310 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4320 if(!BuffersOrContinuationNowFlag)
4322 if(NextSpeedLimit < LimitingSpeed)
4324 LimitingSpeed = NextSpeedLimit;
4328 int TempMaxExitSpeed;
4332 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4334 MaxExitSpeedAtHalfBraking = 0;
4338 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4340 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4342 TempMaxExitSpeed = FrontElementMaxSpeed;
4346 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4357 TempBrakeRate = ((
EntrySpeed *
EntrySpeed) - (LimitingSpeed * LimitingSpeed)) / 3.6 / 3.6 / 2 / CumulativeLength;
4370 if(!BuffersOrContinuationNowFlag)
4372 CurrentTrackVectorPosition = NextTrackVectorPosition;
4373 EntryPos = NextEntryPos;
4374 CurrentElementHalfLength = NextElementHalfLength;
4377 ContinuationNextFlag =
true;
4381 while(((CumulativeLength -
FrontElementLength) < DistanceAtHalfBraking) && ((!BuffersOrContinuationNowFlag && !ContinuationNextFlag) ||
4401 if(ExitSpeedHalfSquared < 10)
4411 if(ExitSpeedFullSquared < 10)
4474 double DeltaExitTimeToMaxInSecs;
4475 double DistanceToMax;
4484 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4486 DistanceToMax = EntryHalfLength;
4489 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4490 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4507 double DeltaExitTimeToMaxInSecs;
4508 double DistanceToMax;
4517 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4519 DistanceToMax = EntryHalfLength / 2;
4522 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4523 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4534 if(ExitSpeedHalfSquared < 10)
4544 if(ExitSpeedFullSquared < 10)
4563 if((EntryPos == 0) || (EntryPos == 2))
4585 if(NextTrackVectorPosition > -1)
4587 int NextElementLength;
4588 if(NextEntryPos > 1)
4596 double NextStoppingSpeed = sqrt(3.6 * 3.6 * 2 *
BrakeRate * NextElementLength);
4783 int ElementCount = 0;
4791 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition;
4809 CurrentTrackVectorPosition).
Attribute != 4))
4849 if((EntryPos == 0) || (EntryPos == 2))
4871 CurrentTrackVectorPosition = NextTrackVectorPosition;
4872 EntryPos = NextEntryPos;
4874 if(ElementCount > 1000)
4902 throw Exception(
"Error - failed to set ReturnVal in ClearToNextSignal()");
4927 bool PlatformFoundFlag =
false, StopRequired =
false, SkipRouteCheck =
false, RouteOrPartRouteSet =
false;
4928 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition, ElementNumber = 0, Distance = 0;
4929 int RouteStartPosition;
4931 int PlatformPosition;
4933 int EntryPos =
LeadEntryPos, ExitPos, NextEntryPos, RouteID;
4949 if(Distance > (4000 + LeadElementDistance))
4972 if(OtherTrain.
LeadElement == CurrentTrackVectorPosition)
4975 if((OtherCommand ==
"Fjo") || (OtherCommand ==
"jbo") || (OtherCommand ==
"cdt") || (OtherCommand ==
"Frh") ||
5021 if(!PlatformFoundFlag)
5023 PlatformPosition = CurrentTrackVectorPosition;
5026 PlatformFoundFlag =
true;
5042 if((EntryPos == 0) || (EntryPos == 2))
5086 if(ElementNumber < 2)
5088 SkipRouteCheck =
true;
5092 SkipRouteCheck =
false;
5094 if(ElementNumber == 1)
5096 RouteStartPosition = CurrentTrackVectorPosition;
5106 if(ElementNumber > 1)
5110 RouteOrPartRouteSet =
true;
5114 RouteOrPartRouteSet =
false;
5117 if(!SkipRouteCheck && !RouteOrPartRouteSet)
5124 int ExitLink = CurrentTrackElement.
Link[ExitPos];
5125 if((ExitLink == 1) || (ExitLink == 3) || (ExitLink == 7) || (ExitLink == 9))
5137 Distance += CurrentTrackElement.
Length01;
5141 Distance += CurrentTrackElement.
Length23;
5143 NextTrackVectorPosition = CurrentTrackElement.
Conn[ExitPos];
5144 NextEntryPos = CurrentTrackElement.
ConnLinkPos[ExitPos];
5145 CurrentTrackVectorPosition = NextTrackVectorPosition;
5146 EntryPos = NextEntryPos;
5183 return(RepeatHeadCode);
5205 bool FrontValid =
false, RearValid =
false;
5206 TTrackElement FrontAdjacentTrackElement, RearAdjacentTrackElement;
5210 TrainToBeJoinedBy = NULL;
5224 int TrainToBeJoinedByID = -1;
5245 if((TrainToBeJoinedByID < 0) && RearValid)
5264 if(TrainToBeJoinedByID < 0)
5266 TrainToBeJoinedBy = NULL;
5271 if(!TrainToBeJoinedBy->
Stopped())
5273 TrainToBeJoinedBy = NULL;
5284 TDateTime TimetableNonRepeatTime,
bool Warning)
5319 AnsiString(ActionType) +
"," + LocationName +
"," +
HeadCode);
5320 AnsiString BaseLog =
"", WarningBaseLog =
"", PerfLog =
"", ActionLog =
"";
5321 int IntMinsLate = 0;
5326 ActionLog =
" arrived at ";
5335 ActionLog =
" terminated at ";
5340 ActionLog =
" departed from ";
5342 if(ActionType ==
Pass)
5344 ActionLog =
" passed ";
5348 ActionLog =
" created at ";
5350 if(ActionType ==
Enter)
5352 ActionLog =
" entered railway at ";
5354 if(ActionType ==
Leave)
5356 ActionLog =
" left railway at ";
5360 ActionLog =
" split from front to ";
5364 ActionLog =
" split from rear to ";
5368 ActionLog =
" joined by ";
5372 ActionLog =
" changed direction at ";
5376 ActionLog =
" became new service ";
5380 ActionLog =
" taken under signaller control at ";
5384 ActionLog =
" restored to timetable control at ";
5390 ActionLog =
" REMOVED FROM RAILWAY DUE TO CRASH at ";
5394 ActionLog =
" REMOVED FROM RAILWAY DUE TO DERAILMENT at ";
5398 ActionLog =
" REMOVED FROM RAILWAY at ";
5403 ActionLog =
" received signaller authority to proceed";
5407 ActionLog =
" received signaller authority to step forward";
5411 ActionLog =
" changed direction under signaller control at ";
5415 ActionLog =
" received signaller authority to pass red signal";
5419 ActionLog =
" received signaller instruction to stop";
5423 ActionLog =
" stopped on signaller instruction ";
5427 ActionLog =
" joined under signaller control by ";
5431 ActionLog =
" suffered an onboard power failure at ";
5435 ActionLog =
" failure repaired at ";
5439 ActionLog =
" left railway under signaller control at ";
5441 if(OtherHeadCode !=
"")
5443 OtherHeadCode +=
" at ";
5450 WarningBaseLog =
HeadCode + ActionLog + OtherHeadCode + LocationName;
5456 bool TimePerformance =
true;
5464 TimePerformance =
false;
5468 double MinsLate = ((double)(ActualTime -
GetTrainTime(1, TimetableNonRepeatTime))) * 1440;
5470 if(ActionType ==
Pass)
5484 IntMinsLate = int(ceil(MinsLate));
5488 IntMinsLate = int(floor(MinsLate));
5490 if(IntMinsLate == 0)
5492 PerfLog =
" on time";
5494 else if(IntMinsLate == 1)
5496 PerfLog =
" 1 minute late";
5498 else if(IntMinsLate == -1)
5500 PerfLog =
" 1 minute early";
5502 else if(IntMinsLate > 1)
5504 PerfLog =
" " + AnsiString(IntMinsLate) +
" minutes late";
5506 else if(IntMinsLate < -1)
5508 int PosIntMinsLate = -IntMinsLate;
5509 PerfLog =
" " + AnsiString(PosIntMinsLate) +
" minutes early";
5511 if(LocationName.Pos(
'-') > 0)
5513 PerfLog =
"," + PerfLog;
5527 if((ActionType ==
Arrive) && (IntMinsLate == 0))
5531 else if((ActionType ==
Arrive) && (IntMinsLate > 0))
5536 else if((ActionType ==
Arrive) && (IntMinsLate < 0))
5542 else if((ActionType ==
Pass) && (IntMinsLate == 0))
5546 else if((ActionType ==
Pass) && (IntMinsLate > 0))
5551 else if((ActionType ==
Pass) && (IntMinsLate < 0))
5557 else if((ActionType ==
Leave) && (IntMinsLate == 0))
5561 else if((ActionType ==
Leave) && (IntMinsLate > 0))
5566 else if((ActionType ==
Leave) && (IntMinsLate < 0))
5572 else if((ActionType ==
Depart) && (IntMinsLate == 0))
5576 else if((ActionType ==
Depart) && (IntMinsLate > 0))
5595 AnsiString LocName =
"";
5662 if(LocationName ==
"")
5666 int FirstNamedElementPos, SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos;
5667 int RearTrainRearPosition, RearTrainFrontPosition, RearTrainExitPos;
5668 int FrontTrainRearPosition, FrontTrainFrontPosition, FrontTrainExitPos;
5672 if(LocationName !=
"")
5680 SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos))
5685 SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos))
5699 int LeadPosA = FirstNamedElementPos;
5700 int LeadPosB = FirstNamedLinkedElementPos;
5701 int LeadPosC = SecondNamedElementPos;
5702 int LeadPosD = SecondNamedLinkedElementPos;
5704 int LeadNumAtLoc = 0;
5721 if(LeadNumAtLoc < 4)
5725 SecondNamedLinkedElementPos))
5727 FirstNamedElementPos = LeadPosA;
5728 FirstNamedLinkedElementPos = LeadPosB;
5729 SecondNamedElementPos = LeadPosC;
5730 SecondNamedLinkedElementPos = LeadPosD;
5734 int MidNumAtLoc = 0;
5751 if(LeadNumAtLoc > MidNumAtLoc)
5754 FirstNamedElementPos = LeadPosA;
5755 FirstNamedLinkedElementPos = LeadPosB;
5756 SecondNamedElementPos = LeadPosC;
5757 SecondNamedLinkedElementPos = LeadPosD;
5771 throw Exception(
"Error - LocationName not set in FrontTrainSplit");
5781 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5782 FrontTrainRearPosition = FirstNamedElementPos;
5783 RearTrainFrontPosition = SecondNamedElementPos;
5784 RearTrainRearPosition = SecondNamedLinkedElementPos;
5788 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5789 FrontTrainRearPosition = SecondNamedElementPos;
5790 RearTrainFrontPosition = FirstNamedElementPos;
5791 RearTrainRearPosition = FirstNamedLinkedElementPos;
5798 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5799 FrontTrainRearPosition = SecondNamedElementPos;
5800 RearTrainFrontPosition = FirstNamedElementPos;
5801 RearTrainRearPosition = FirstNamedLinkedElementPos;
5805 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5806 FrontTrainRearPosition = FirstNamedElementPos;
5807 RearTrainFrontPosition = SecondNamedElementPos;
5808 RearTrainRearPosition = SecondNamedLinkedElementPos;
5811 RearTrainExitPos = -1;
5812 for(
int x = 0; x < 4; x++)
5816 RearTrainExitPos = x;
5820 if(RearTrainExitPos == -1)
5822 throw Exception(
"Error - RearTrainRearPosition not linked to RearTrainFrontPosition in FrontTrainSplit");
5824 FrontTrainExitPos = -1;
5825 for(
int x = 0; x < 4; x++)
5829 FrontTrainExitPos = x;
5833 if(FrontTrainExitPos == -1)
5835 throw Exception(
"Error - FrontTrainRearPosition not linked to FrontTrainFrontPosition in FrontTrainSplit");
5838 int TrainIDOnRearOfRearTrain, TrainIDOnFrontOfRearTrain, TrainIDOnRearOfFrontTrain, TrainIDOnFrontOfFrontTrain;
5845 else if((RearMostElement.
TrackType ==
Bridge) && (RearTrainExitPos < 2))
5865 else if((FrontMostElement.
TrackType ==
Bridge) && (FrontTrainExitPos < 2))
5873 if(((TrainIDOnRearOfRearTrain > -1) && (TrainIDOnRearOfRearTrain !=
TrainID)) || ((TrainIDOnFrontOfRearTrain > -1) && (TrainIDOnFrontOfRearTrain !=
TrainID)
5874 ) || ((TrainIDOnRearOfFrontTrain > -1) && (TrainIDOnRearOfFrontTrain !=
TrainID)) ||
5875 ((TrainIDOnFrontOfFrontTrain > -1) && (TrainIDOnFrontOfFrontTrain !=
TrainID)))
5972 if(LocationName ==
"")
5976 int FirstNamedElementPos, SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos;
5977 int RearTrainRearPosition, RearTrainFrontPosition, RearTrainExitPos;
5978 int FrontTrainRearPosition, FrontTrainFrontPosition, FrontTrainExitPos;
5982 if(LocationName !=
"")
5989 SecondNamedLinkedElementPos))
5993 SecondNamedLinkedElementPos))
6007 int LeadPosA = FirstNamedElementPos;
6008 int LeadPosB = FirstNamedLinkedElementPos;
6009 int LeadPosC = SecondNamedElementPos;
6010 int LeadPosD = SecondNamedLinkedElementPos;
6012 int LeadNumAtLoc = 0;
6029 if(LeadNumAtLoc < 4)
6033 SecondNamedLinkedElementPos))
6035 FirstNamedElementPos = LeadPosA;
6036 FirstNamedLinkedElementPos = LeadPosB;
6037 SecondNamedElementPos = LeadPosC;
6038 SecondNamedLinkedElementPos = LeadPosD;
6042 int MidNumAtLoc = 0;
6059 if(LeadNumAtLoc > MidNumAtLoc)
6062 FirstNamedElementPos = LeadPosA;
6063 FirstNamedLinkedElementPos = LeadPosB;
6064 SecondNamedElementPos = LeadPosC;
6065 SecondNamedLinkedElementPos = LeadPosD;
6079 throw Exception(
"Error - LocationName not set in RearTrainSplit");
6089 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
6090 FrontTrainRearPosition = FirstNamedElementPos;
6091 RearTrainFrontPosition = SecondNamedElementPos;
6092 RearTrainRearPosition = SecondNamedLinkedElementPos;
6096 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
6097 FrontTrainRearPosition = SecondNamedElementPos;
6098 RearTrainFrontPosition = FirstNamedElementPos;
6099 RearTrainRearPosition = FirstNamedLinkedElementPos;
6106 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
6107 FrontTrainRearPosition = SecondNamedElementPos;
6108 RearTrainFrontPosition = FirstNamedElementPos;
6109 RearTrainRearPosition = FirstNamedLinkedElementPos;
6113 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
6114 FrontTrainRearPosition = FirstNamedElementPos;
6115 RearTrainFrontPosition = SecondNamedElementPos;
6116 RearTrainRearPosition = SecondNamedLinkedElementPos;
6119 RearTrainExitPos = -1;
6120 for(
int x = 0; x < 4; x++)
6124 RearTrainExitPos = x;
6128 if(RearTrainExitPos == -1)
6130 throw Exception(
"Error - RearTrainRearPosition not linked to RearTrainFrontPosition in RearTrainSplit");
6132 FrontTrainExitPos = -1;
6133 for(
int x = 0; x < 4; x++)
6137 FrontTrainExitPos = x;
6141 if(FrontTrainExitPos == -1)
6143 throw Exception(
"Error - FrontTrainRearPosition not linked to FrontTrainFrontPosition in RearTrainSplit");
6146 int TrainIDOnRearOfRearTrain, TrainIDOnFrontOfRearTrain, TrainIDOnRearOfFrontTrain, TrainIDOnFrontOfFrontTrain;
6153 else if((RearMostElement.
TrackType ==
Bridge) && (RearTrainExitPos < 2))
6173 else if((FrontMostElement.
TrackType ==
Bridge) && (FrontTrainExitPos < 2))
6181 if(((TrainIDOnRearOfRearTrain > -1) && (TrainIDOnRearOfRearTrain !=
TrainID)) || ((TrainIDOnFrontOfRearTrain > -1) && (TrainIDOnFrontOfRearTrain !=
TrainID)
6182 ) || ((TrainIDOnRearOfFrontTrain > -1) && (TrainIDOnRearOfFrontTrain !=
TrainID)) ||
6183 ((TrainIDOnFrontOfFrontTrain > -1) && (TrainIDOnFrontOfFrontTrain !=
TrainID)))
6322 TTrain *TrainToBeJoinedBy;
6355 double OtherBrakeForce = TrainToBeJoinedBy->
MaxBrakeRate * TrainToBeJoinedBy->
Mass;
6357 double CombinedBrakeRate = (OtherBrakeForce + OwnBrakeForce) / (TrainToBeJoinedBy->
Mass +
Mass);
6417 int RouteNumber = -1;
6422 int CorrectRouteID = OR.
RouteID;
6427 bool FirstPass =
true;
6432 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
6539 for(
int x = 0; x < IncNum; x++)
6572 else if(Ptr->
Command ==
"jbo")
6583 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
6589 bool IncludeFER =
false;
6597 if(!IncludeFER && (Ptr->
Command ==
"Fer"))
6602 else if(IncludeFER && (Ptr->
Command ==
"Fer"))
6613 else if(Ptr->
Command ==
"Fjo")
6619 else if(Ptr->
Command ==
"Frh")
6629 else if(Ptr->
Command ==
"Frh-sh")
6680 else if(Ptr->
Command ==
"jbo")
6685 else if(Ptr->
Command ==
"cdt")
6693 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
7080 int RouteNumber = -1;
7085 int CorrectRouteID = OR.
RouteID;
7090 bool FirstPass =
true;
7095 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
7123 ",FloatingLabelNextString" +
"," +
HeadCode);
7124 AnsiString RetStr =
"", LocationName =
"";
7128 throw Exception(
"Error - start entry in FloatingLabelNextString");
7172 else if(Ptr->
Command ==
"Fns")
7178 else if(Ptr->
Command ==
"F-nshs")
7209 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7211 else if(Ptr->
Command ==
"Frh")
7213 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7215 else if(Ptr->
Command ==
"Fer")
7217 AnsiString AllowedExits =
"";
7220 else if(Ptr->
Command ==
"Fjo")
7225 else if(Ptr->
Command ==
"jbo")
7230 else if(Ptr->
Command ==
"fsp")
7235 else if(Ptr->
Command ==
"rsp")
7240 else if(Ptr->
Command ==
"cdt")
7253 + AnsiString(RptNum) +
",GetNewServiceDepartureInfo," +
HeadCode);
7254 AnsiString DepTime =
"", EventTime =
"";
7255 bool CDTFlag =
false;
7257 AnsiString CurrentLocation = NewServiceAV.at(0).LocationName;
7258 AnsiString TowardsLocation =
"";
7261 if((AVI->LocationName != CurrentLocation) && (AVI->LocationName !=
"") && (TowardsLocation ==
""))
7263 TowardsLocation = AVI->LocationName;
7265 else if((AVI->Command ==
"Fer") && (TowardsLocation ==
"") && !AVI->ExitList.empty())
7274 TowardsLocation = AnsiString(
"track element ID ") + TE.
ElementID;
7280 if(AVI->Command ==
"cdt")
7285 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
7288 RetStr +=
"\nNew service splits at " + EventTime;
7292 if(AVI->Command ==
"jbo")
7295 RetStr +=
"\nNew service joined by " + AVI->OtherHeadCode +
" at " + EventTime;
7299 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
7304 if(TowardsLocation !=
"")
7306 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at " + DepTime;
7310 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
7315 if(TowardsLocation !=
"")
7317 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at " + DepTime;
7321 RetStr +=
"\nNew service departs at " + DepTime;
7339 ",FloatingTimetableString" +
"," +
HeadCode);
7340 AnsiString RetStr =
"", PartStr =
"";
7342 bool SkipDep =
false, SkipDepActedOn =
false;
7348 throw Exception(
"Error - start entry in FloatingTimetableString");
7351 bool FirstPass =
true;
7364 AnsiString TrainLoc =
"";
7410 AnsiString TrainLoc =
"";
7450 else if(Ptr->
Command ==
"Fns")
7456 else if(Ptr->
Command ==
"F-nshs")
7489 else if(Ptr->
Command ==
"Frh")
7493 else if(Ptr->
Command ==
"Fer")
7495 AnsiString AllowedExits =
"";
7498 else if(Ptr->
Command ==
"Fjo")
7503 else if(Ptr->
Command ==
"jbo")
7508 else if(Ptr->
Command ==
"fsp")
7513 else if(Ptr->
Command ==
"rsp")
7518 else if(Ptr->
Command ==
"cdt")
7524 RetStr = RetStr +
'\n' + PartStr;
7538 SkipDepActedOn =
true;
7549 RetStr =
"Timetable finished";
7553 RetStr =
"No timetable";
7557 return(
"Timetable:\n" + RetStr);
7710 bool ForwardHeadCode;
7714 ForwardHeadCode =
true;
7719 ForwardHeadCode =
false;
7862 if(ColourNumber == 0)
7866 else if(ColourNumber == 1)
7870 else if(ColourNumber == 2)
7874 else if(ColourNumber == 3)
7878 else if(ColourNumber == 4)
7882 else if(ColourNumber == 5)
7886 else if(ColourNumber == 6)
7890 else if(ColourNumber == 7)
7894 else if(ColourNumber == 8)
7898 else if(ColourNumber == 9)
7902 else if(ColourNumber == 10)
7906 else if(ColourNumber == 11)
7910 else if(ColourNumber == 12)
7914 else if(ColourNumber == 13)
7918 else if(ColourNumber == 14)
7930 for(
int x = 0; x < 4; x++)
7937 for(
int x = 0; x < 4; x++)
8022 if((LocationAndMarker[1] !=
'*') && (LocationAndMarker.Length() > 6))
8025 AnsiString Location = LocationAndMarker.SubString(1, LocationAndMarker.Length() - 6);
8026 bool GiveMessagesFalse =
false;
8027 bool CheckLocationsExistInRailwayTrue =
true;
8034 AnsiString Marker = LocationAndMarker.SubString(LocationAndMarker.Length() - 5, 6);
8037 if(Marker[6] ==
'1')
8502 bool HideFlashingTrain =
true;
8505 Graphics::TBitmap *SmallTrainBitmap;
8546 HideFlashingTrain =
false;
8551 HideFlashingTrain =
false;
8556 HideFlashingTrain =
false;
8561 HideFlashingTrain =
false;
8566 HideFlashingTrain =
false;
8570 if((
LeadElement > -1) && (!HideFlashingTrain || Flash))
8574 if((
MidElement > -1) && (!HideFlashingTrain || Flash))
8598 for(
int y = 0; y < 3; y++)
8602 bool FoundFlag =
false;
8613 if(IMPair.first != IMPair.second)
8640 if((LocationName ==
"") && (
MidElement > -1))
8644 if((LocationName ==
"") && (
LagElement > -1))
8648 if(LocationName ==
"")
8650 throw Exception(
"Error - Location name not set in TrainAtLocation");
8661 for(
int x = 0; x < 4; x++)
8673 for(
int x = 0; x < 4; x++)
8690 AnsiString(LinkNumber) +
"," +
HeadCode);
8742 int DistanceToRedSignal = 0, DistanceToExit = -1;
8743 float TimeToAct = 0, LastTimeToExit =
TimeToExit;
8747 float MinsEarly = 0;
8748 TDateTime DepartureTime;
8749 TDateTime ArrivalTime;
8777 if(TempTTE < LastTimeToExit)
8812 if(TempTTE < LastTimeToExit)
8835 if(TempTTE < LastTimeToExit)
8865 if(TempTTE < LastTimeToExit)
8888 if(TempTTE < LastTimeToExit)
8931 float CurrentStopTime;
8932 float LaterStopTime;
8933 float RecoverableTime;
8941 if((DistanceToRedSignal == -1) && (DistanceToExit == -1))
8948 bool DistanceToRedSignalSet = (DistanceToRedSignal > -1);
8949 bool DistanceToExitSet = (DistanceToExit > -1);
8950 int GenericDistance = DistanceToRedSignal;
8951 if(DistanceToExitSet)
8953 GenericDistance = DistanceToExit;
8969 float TimeToSubtract, TotalStopTime;
8972 TimeToSubtract = RecoverableTime;
9015 if(CurrentStopTime > 0)
9017 TotalStopTime = CurrentStopTime + LaterStopTime;
9026 else if((MinsEarly > 0) && !
Stopped())
9028 TotalStopTime = LaterStopTime + MinsEarly;
9032 if(LaterStopTime == 0)
9034 TotalStopTime = CurrentStopTime;
9040 TotalStopTime = CurrentStopTime + LaterStopTime - TimeToSubtract;
9043 if(AvTrackSpeed < 30)
9047 int Speed = AvTrackSpeed;
9057 if(DistanceToRedSignalSet)
9059 TimeToAct = TotalStopTime + GenericDistance * 3.6 / 60 / Speed;
9069 TimeToExit = TotalStopTime + GenericDistance * 3.6 / 60 / Speed;
9092 if((NextEntryPos == 0) || (NextEntryPos == 2))
9219 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9261 int IncrementalMinutes = 0;
9262 int IncrementalDigits = 0;
9270 throw Exception(
"Error - Repeat entry && less than two trains for Snt entry: " + TDEntry.
HeadCode);
9305 if(AVEntry0.
Command ==
"Snt-sh")
9310 int IncrementalMinutes = 0;
9311 int IncrementalDigits = 0;
9319 throw Exception(
"Error - Repeat entry && less than two trains for Snt-sh entry: " + TDEntry.
HeadCode);
9362 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9442 AnsiString Loc =
"";
9443 bool ElementFound =
false;
9448 ElementFound =
true;
9453 ElementFound =
true;
9458 ElementFound =
true;
9487 else if(AVEntryPtr->
Command ==
"Fer")
9489 bool CorrectExit =
false;
9601 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9619 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9634 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9645 bool TTrainController::AddTrain(
int Caller,
int RearPosition,
int FrontPosition, AnsiString HeadCode,
int StartSpeed,
int Mass,
double MaxRunningSpeed,
9646 double MaxBrakeRate,
double PowerAtRail, AnsiString ModeStr,
TTrainDataEntry *TrainDataEntryPtr,
int RepeatNumber,
int IncrementalMinutes,
9647 int IncrementalDigits,
int SignallerSpeed,
bool SignallerControl,
TActionEventType &EventType)
9649 LogEvent(AnsiString(Caller) +
",AddTrain," + AnsiString(RearPosition) +
"," + AnsiString(FrontPosition) +
"," + HeadCode +
"," + AnsiString(StartSpeed) +
9650 "," + AnsiString(Mass) +
"," + ModeStr);
9652 "," + HeadCode +
"," + AnsiString(StartSpeed) +
"," + AnsiString(Mass) +
"," + ModeStr);
9654 int RearExitPos = -1;
9656 for(
int x = 0; x < 4; x++)
9663 if(RearExitPos == -1)
9665 throw Exception(
"Error, RearExit == -1 in AddTrain");
9667 bool ReportFlag =
true;
9684 if(ModeStr ==
"Timetable")
9690 if(MaxRunningSpeed < 10)
9692 MaxRunningSpeed = 10;
9694 if(SignallerSpeed < 10)
9696 SignallerSpeed = 10;
9698 TTrain *NewTrain =
new TTrain(0, RearPosition, RearExitPos, HeadCode, StartSpeed, Mass, MaxRunningSpeed, MaxBrakeRate, PowerAtRail, TrainMode,
9699 TrainDataEntryPtr, RepeatNumber, IncrementalMinutes, IncrementalDigits, SignallerSpeed);
9706 if(SignallerControl)
9736 if(!SignallerControl)
9751 if(!SignallerControl)
9762 AnsiString Loc =
"";
9779 if(!SignallerControl)
9798 int RouteNumber = -1;
9799 bool SignalsSet =
false;
9806 int RouteStartPosition;
9810 if(FirstPair.first == RouteNumber)
9812 RouteStartPosition = FirstPair.second;
9814 else if(SecondPair.first == RouteNumber)
9816 RouteStartPosition = SecondPair.second;
9820 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 1st of 2 calls to SetAllRearwardsSignals in AddTrain");
9826 else if(RouteNumber > -1)
9846 int LinkedRouteNumber = -1;
9867 int RouteStartPosition;
9871 if(FirstPair.first == RouteNumber)
9873 RouteStartPosition = FirstPair.second;
9875 else if(SecondPair.first == RouteNumber)
9877 RouteStartPosition = SecondPair.second;
9881 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 2nd of 2 calls to SetAllRearwardsSignals in AddTrain");
9887 else if(RouteNumber > -1)
9907 int LinkedRouteNumber = -1;
9928 AnsiString(TrackVectorNumber));
9931 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9940 throw Exception(
"Error, VecPos not set in EntryPos");
9942 if(
TrainVectorAt(2, VecPos).LeadElement == TrackVectorNumber)
9947 else if(
TrainVectorAt(4, VecPos).MidElement == TrackVectorNumber)
9952 else if(
TrainVectorAt(6, VecPos).LagElement == TrackVectorNumber)
9966 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9974 throw Exception(
"Error - No Train identified in TrainVectorAtIdent with ID = " + AnsiString(TrainID));
9984 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10005 return(RepeatTime);
10014 AnsiString RetStr =
"", PartStr =
"";
10022 if((Ptr->Command !=
"") && (Ptr->Command[1] ==
'S'))
10030 if(Ptr->SignallerControl)
10032 RetStr =
"Train under signaller control";
10037 if(Ptr->ArrivalTime == Ptr->DepartureTime)
10048 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime != TDateTime(-1)))
10052 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime == TDateTime(-1)))
10056 else if(Ptr->FormatType ==
PassTime)
10060 else if(Ptr->Command ==
"Fns")
10066 else if(Ptr->Command ==
"F-nshs")
10069 Ptr->NonRepeatingShuttleLinkHeadCode +
" at " + Ptr->LocationName;
10076 else if((Ptr->Command ==
"Fns-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
10083 else if((Ptr->Command ==
"Fns-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
10086 Ptr->NonRepeatingShuttleLinkHeadCode, +
" at " + Ptr->LocationName;
10089 else if((Ptr->Command ==
"Frh-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
10096 else if((Ptr->Command ==
"Frh-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
10098 PartStr =
"Terminate at " + Ptr->LocationName;
10100 else if(Ptr->Command ==
"Frh")
10102 PartStr =
"Terminate at " + Ptr->LocationName;
10104 else if(Ptr->Command ==
"Fer")
10106 AnsiString AllowedExits;
10110 else if(Ptr->Command ==
"Fjo")
10113 Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
10115 else if(Ptr->Command ==
"jbo")
10118 (50, Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
10120 else if(Ptr->Command ==
"fsp")
10125 else if(Ptr->Command ==
"rsp")
10130 else if(Ptr->Command ==
"cdt")
10136 RetStr = RetStr +
'\n' + PartStr;
10144 while(Ptr < TTDEPtr->ActionVector.end() && (Count < 33) && ((Ptr->Command ==
"") || ((Ptr->Command !=
"") && (Ptr->Command[1] !=
'F'))));
10157 + AnsiString(RptNum) +
",ControllerGetNewServiceDepartureInfo," + TDEPtr->
HeadCode);
10158 AnsiString DepTime =
"", EventTime =
"";
10159 bool CDTFlag =
false;
10161 AnsiString CurrentLocation = NewServiceAV.at(0).LocationName;
10162 AnsiString TowardsLocation =
"";
10165 if((AVI->LocationName != CurrentLocation) && (AVI->LocationName !=
"") && (TowardsLocation ==
""))
10167 TowardsLocation = AVI->LocationName;
10169 else if((AVI->Command ==
"Fer") && (TowardsLocation ==
"") && !AVI->ExitList.empty())
10178 TowardsLocation = AnsiString(
"track element ID ") + TE.
ElementID;
10184 if(AVI->Command ==
"cdt")
10186 CDTFlag = !CDTFlag;
10189 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
10192 RetStr +=
"\nNew service splits at " + EventTime;
10196 if(AVI->Command ==
"jbo")
10199 RetStr +=
"\nNew service joined by " + AVI->OtherHeadCode +
" at " + EventTime;
10203 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
10208 if(TowardsLocation !=
"")
10210 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at " + DepTime;
10214 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
10219 if(TowardsLocation !=
"")
10221 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at " + DepTime;
10225 RetStr +=
"\nNew service departs at " + DepTime;
10386 ActiveTrackElementNameMapEntry.second = 0;
10392 std::ifstream TTBLFile(FileName, std::ios_base::binary);
10395 if(TTBLFile.is_open())
10397 char *TrainTimetableString =
new char[10000];
10399 bool EndOfFile =
false;
10402 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
10404 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
10411 delete[] TrainTimetableString;
10415 AnsiString OneLine(TrainTimetableString);
10416 bool FinalCallFalse =
false;
10417 while((Count == 0) && !
ProcessOneTimetableLine(5, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
10421 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
10422 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
10427 TimetableMessage(GiveMessages,
"Timetable invalid - unable to find a valid start time on its own line");
10429 delete[] TrainTimetableString;
10433 OneLine = AnsiString(TrainTimetableString);
10439 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
10441 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
10451 OneLine = AnsiString(TrainTimetableString);
10453 if(OneLine.Length() > 9999)
10455 TimetableMessage(GiveMessages,
"Timetable contains a line that is too long - 10,000 or more characters!");
10457 delete[] TrainTimetableString;
10461 bool FinalCallFalse =
false;
10462 if(!
ProcessOneTimetableLine(6, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
10466 delete[] TrainTimetableString;
10470 if(EndOfFile && (Count < 2))
10473 TimetableMessage(GiveMessages,
"Timetable has too few or no relevant entries - must have a start time on its own line and at least one train");
10475 delete[] TrainTimetableString;
10481 delete[] TrainTimetableString;
10486 TimetableMessage(GiveMessages,
"Failed to open timetable file, make sure it's spelled correctly, it exists and isn't open in another application");
10497 bool CheckLocationsExistInRailway)
10622 AnsiString((
short)FinalCall) +
"," + AnsiString((
short)CheckLocationsExistInRailway));
10632 if(OneLine[1] !=
'*')
10634 int SCPos = OneLine.Pos(
';');
10645 bool AllCommas =
true;
10647 for(
int x = 1; x < OneLine.Length() + 1; x++)
10649 if(OneLine[x] !=
',')
10654 if(AllCommas || (OneLine ==
""))
10669 AnsiString First =
"", Second =
"", Third =
"", Fourth =
"";
10670 int RearStartOrRepeatMins = 0, FrontStartOrRepeatDigits = 0, NumberOfRepeats = 0;
10671 TDateTime EventTime(0), ArrivalTime(0), DepartureTime(0);
10672 TDateTime StartTime(0);
10674 bool Warning =
false;
10701 AnsiString TrainInfoStr =
"", HeadCode =
"", Description =
"";
10702 int StartSpeed = 0, MaxRunningSpeed = 0, Mass = 0;
10703 double MaxBrakeRate = 0;
10704 double PowerAtRail = 0;
10705 int SignallerSpeed = 0;
10706 if(OneLine[1] ==
'*')
10712 int Pos = OneLine.Pos(
',');
10715 int SubStringLength = 20;
10716 if(OneLine.Length() < 20)
10718 SubStringLength = OneLine.Length();
10720 TimetableMessage(GiveMessages,
"Error in timetable - entry incomplete: see '" + OneLine.SubString(1, SubStringLength) +
"'....");
10724 TrainInfoStr = OneLine.SubString(1, Pos - 1);
10725 if(!
SplitTrainInfo(0, TrainInfoStr, HeadCode, Description, StartSpeed, MaxRunningSpeed, Mass, MaxBrakeRate, PowerAtRail, SignallerSpeed,
10735 TempTrainDataEntry.
HeadCode = HeadCode;
10739 TempTrainDataEntry.
Mass = Mass;
10747 AnsiString NewRemainder = OneLine.SubString(Pos + 1, OneLine.Length() - Pos);
10750 while(NewRemainder[NewRemainder.Length()] ==
',')
10752 if(NewRemainder.Length() > 1)
10754 NewRemainder = NewRemainder.SubString(1, NewRemainder.Length() - 1);
10763 if(NewRemainder ==
"")
10765 TimetableMessage(GiveMessages,
"Error in timetable - no events following train: '" + OneLine +
"'");
10770 int CommaCount = 0;
10771 for(
int x = 1; x < NewRemainder.Length() + 1; x++)
10773 if(NewRemainder[x] ==
',')
10778 if(CommaCount == 0)
10780 if((NewRemainder.SubString(7, 3) !=
"Snt") || (NewRemainder[NewRemainder.Length()] !=
'S'))
10782 int SubStringLength = 20;
10783 if(OneLine.Length() < 20)
10785 SubStringLength = OneLine.Length();
10788 "Error in timetable - must have at least a start and a finish event for a train that is not started under signaller control - see line beginning: '" +
10789 OneLine.SubString(1, SubStringLength) +
"'....");
10794 AnsiString OneEntry =
"";
10799 bool FinishFlag =
false;
10800 for(
int x = 0; x < CommaCount + 1; x++)
10802 if((CommaCount == 0) || (x < CommaCount))
10807 if(CommaCount == 0)
10809 OneEntry = NewRemainder;
10814 Pos = NewRemainder.Pos(
',');
10815 OneEntry = NewRemainder.SubString(1, Pos - 1);
10816 NewRemainder = NewRemainder.SubString(Pos + 1, NewRemainder.Length() - Pos);
10822 RearStartOrRepeatMins = 0;
10823 FrontStartOrRepeatDigits = 0;
10824 NumberOfRepeats = 0;
10825 if(!
SplitEntry(0, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
10826 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
10828 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'");
10833 if(Warning && (Second ==
"Frh"))
10835 TimetableMessage(GiveMessages,
"Error in line - '" + OneEntry +
"': warnings cannot be given for 'Frh' events");
10839 if(Warning && (Second ==
"Fjo"))
10842 "': warnings cannot be given for 'Fjo' events, for a train join warning add a 'W' prefix to the 'jbo' event");
10848 if(SequenceType !=
Start)
10850 TimetableMessage(GiveMessages,
"Error in timetable - First event not a start event: '" + OneEntry +
"'");
10854 if((Second ==
"Snt") && (Fourth ==
'S') && (NewRemainder !=
""))
10856 if(NewRemainder[1] !=
'R')
10859 "Error in timetable - the only event that can follow a train created under signaller control is a repeat, see '" +
10865 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
10869 if((HeadCode ==
"") || (Description ==
"") || (MaxRunningSpeed == 0) || (Mass == 0) || (MaxBrakeRate == 0))
10872 TimetableMessage(GiveMessages,
"Error in timetable - train information incomplete before 'Snt' or 'Snt-sh' start event: '" +
10878 if((Second ==
"Sfs") || (Second ==
"Sns") || (Second ==
"Sns-sh") || (Second ==
"Sns-fsh"))
10883 TimetableMessage(GiveMessages,
"Error in timetable - headcode missing before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
10888 if((StartSpeed != 0) || (MaxRunningSpeed != 0) || (Mass != 0) || (MaxBrakeRate != 0) || (PowerAtRail != 0))
10891 "Error in timetable - information additional to a headcode & optional description given before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
10898 if(SequenceType ==
Finish)
10907 TDateTime TempTime;
10913 ActionVectorEntry.
Warning = Warning;
10929 ActionVectorEntry.
Command = Second;
10944 else if(FormatType ==
TimeCmd)
10950 ActionVectorEntry.
Command = Second;
10958 ActionVectorEntry.
Command = Second;
10959 ActionVectorEntry.
ExitList = ExitList;
10967 ActionVectorEntry.
Command = Second;
10981 ActionVectorEntry.
Command = Second;
10992 ActionVectorEntry.
Command = Second;
11002 ActionVectorEntry.
Command = Second;
11011 ActionVectorEntry.
Command = Second;
11020 ActionVectorEntry.
Command = Second;
11026 ActionVectorEntry.
Command = Second;
11028 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
11033 OneEntry = NewRemainder;
11038 RearStartOrRepeatMins = 0;
11039 FrontStartOrRepeatDigits = 0;
11040 NumberOfRepeats = 0;
11041 if((FinishFlag) && (OneEntry[1] !=
'R'))
11044 TimetableMessage(GiveMessages,
"Error in timetable - Last event = '" + OneEntry +
"'. An earlier finish event has been found with something other than a repeat following it - only a repeat can follow a finish event.");
11048 if(OneEntry[1] !=
'R')
11050 if(!
SplitEntry(1, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
11051 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
11053 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'");
11057 if(SequenceType !=
Finish)
11059 TimetableMessage(GiveMessages,
"Error in timetable - last event should be a finish: '" + OneEntry +
"'");
11066 TDateTime TempTime;
11072 ActionVectorEntry.
Warning = Warning;
11079 ActionVectorEntry.
Command = Second;
11087 ActionVectorEntry.
Command = Second;
11096 ActionVectorEntry.
Command = Second;
11105 ActionVectorEntry.
Command = Second;
11115 ActionVectorEntry.
Command = Second;
11116 ActionVectorEntry.
ExitList = ExitList;
11120 ActionVectorEntry.
Command = Second;
11122 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
11127 if(!
SplitRepeat(0, OneEntry, RearStartOrRepeatMins, FrontStartOrRepeatDigits, NumberOfRepeats, GiveMessages))
11143 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
11162 if((HeadCode[HeadCode.Length() - 1] <
'0') || (HeadCode[HeadCode.Length() - 1] >
'9'))
11167 if((HeadCode[HeadCode.Length()] <
'0') || (HeadCode[HeadCode.Length()] >
'9'))
11182 if(TimeStr.Length() < 5)
11187 if((TimeStr[1] <
'0') || (TimeStr[1] >
'9'))
11192 if((TimeStr[2] <
'0') || (TimeStr[2] >
'9'))
11197 if(TimeStr[3] !=
':')
11202 if((TimeStr[4] <
'0') || (TimeStr[4] >
'5'))
11207 if((TimeStr[5] <
'0') || (TimeStr[5] >
'9'))
11212 while(TimeStr.Length() > 5)
11214 TimeStr = TimeStr.SubString(1, TimeStr.Length() - 1);
11216 double WholeHours = (AnsiString(TimeStr[1]) + AnsiString(TimeStr[2])).ToDouble();
11217 double FracHour = ((AnsiString(TimeStr[4]) + AnsiString(TimeStr[5])).ToDouble()) / 60.0;
11219 if((WholeHours + FracHour) >= 95.98334)
11224 Time = TDateTime((WholeHours + FracHour) / 24);
11231 bool TTrainController::SplitEntry(
int Caller, AnsiString OneEntry,
bool GiveMessages,
bool CheckLocationsExistInRailway, AnsiString &First, AnsiString &Second,
11232 AnsiString &Third, AnsiString &Fourth,
int &RearStartOrRepeatMins,
int &FrontStartOrRepeatDigits,
TTimetableFormatType &FormatType,
11241 TDateTime TempTime;
11243 if(OneEntry.Length() > 0)
11245 if(OneEntry[1] ==
'W')
11248 OneEntry = OneEntry.SubString(2, OneEntry.Length() - 1);
11252 if(OneEntry ==
"Frh")
11262 if(OneEntry.Length() < 7)
11267 int Pos = OneEntry.Pos(
';');
11275 First = OneEntry.SubString(1, 5);
11281 AnsiString Remainder = OneEntry.SubString(Pos + 1, OneEntry.Length() - Pos);
11283 if((Remainder[1] >=
'0') && (Remainder[1] <=
'9'))
11286 if(Remainder.Length() < 7)
11291 Pos = Remainder.Pos(
';');
11298 Second = Remainder.SubString(1, 5);
11304 Third = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11317 Pos = Remainder.Pos(
';');
11320 Second = Remainder;
11321 if(Second ==
"cdt")
11346 if((Pos != 4) && (Pos != 7) && (Pos != 8))
11352 Second = Remainder.SubString(1, Pos - 1);
11354 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11356 Pos = Remainder.Pos(
';');
11363 Third = Remainder.SubString(1, Pos - 1);
11364 Fourth = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11366 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
11369 int SpacePos = Third.Pos(
' ');
11375 AnsiString RearStartStr = Third.SubString(1, SpacePos - 1);
11376 AnsiString FrontStartStr = Third.SubString(SpacePos + 1, Third.Length() - SpacePos);
11378 if(CheckLocationsExistInRailway)
11388 if(Second ==
"Snt")
11391 SequenceType =
Start;
11400 SequenceType =
Start;
11411 if(Second ==
"Sns-sh")
11415 SequenceType =
Start;
11430 if(Second ==
"F-nshs")
11444 if(Second ==
"Sns-fsh")
11448 SequenceType =
Start;
11458 if(Second ==
"Fns-sh")
11478 if(Second ==
"pas")
11493 if(Second ==
"Fer")
11500 if(CheckLocationsExistInRailway)
11512 if((Second !=
"Fns") && (Second !=
"Fjo") && (Second !=
"jbo") && (Second !=
"fsp") && (Second !=
"rsp") && (Second !=
"Sfs") && (Second !=
"Sns") &&
11513 (Second !=
"Frh-sh"))
11525 if(Second ==
"Frh-sh")
11533 if((Second ==
"Fns") || (Second ==
"Fjo") || (Second ==
"Frh-sh"))
11537 if((Second ==
"jbo") || (Second ==
"fsp") || (Second ==
"rsp"))
11541 if((Second ==
"Sfs") || (Second ==
"Sns"))
11543 SequenceType =
Start;
11561 if((LocStr[1] >=
'0') && (LocStr[1] <=
'9'))
11566 for(
int x = 1; x < LocStr.Length() + 1; x++)
11568 if(LocStr[x] <
' ')
11573 if(LocStr[x] >
'z')
11580 if(CheckLocationsExistInRailway)
11585 "' appears in the timetable but is not a valid name. To be valid the name must be a stopping location and apply to one or more platforms " +
11586 "(not concourses on their own), or to track at a blue non-station named location. BUT NOTE THAT trains can't stop at continuations so a name " +
11587 "that includes a continuation will not be valid.");
11605 if((HeadCode.Length() < 4) || (HeadCode.Length() > 8))
11608 "', length must be between 4 and 8 characters, and last 4 must be a legitimate headcode. This error can also be caused by omitting a service reference after Sns, Snt-sh, Sns-sh, Fns, Fns-sh or Frh-sh");
11613 for(
int x = 1; x < (HeadCode.Length() + 1); x++)
11615 if((HeadCode[x] <
' ') || (HeadCode[x] >
'~'))
11617 TimetableMessage(GiveMessages,
"Non-printable character in headcode '" + HeadCode +
"'");
11623 for(
int x = 3; x >= 0; x--)
11625 if(((HeadCode[HeadCode.Length() - x] <
'A') || (HeadCode[HeadCode.Length() - x] >
'Z')) && ((HeadCode[HeadCode.Length() - x] <
'a') ||
11626 (HeadCode[HeadCode.Length() - x] >
'z')) && ((HeadCode[HeadCode.Length() - x] <
'0') || (HeadCode[HeadCode.Length() - x] >
'9')))
11628 TimetableMessage(GiveMessages,
"Headcode error in '" + HeadCode +
"', headcode must consist of letters and digits only");
11644 AnsiString CurrentID =
"";
11646 if(IDSet.Length() == 0)
11648 TimetableMessage(GiveMessages,
"Must have at least one exit element ID following 'Fer'");
11652 for(
int x = 1; x <= IDSet.Length(); x++)
11655 if(((C <
'0') || (C >
'9')) && (C !=
' ') && (C !=
'N') && (C !=
'-'))
11657 TimetableMessage(GiveMessages,
"Illegal character in the set of element IDs following 'Fer' in '" + IDSet +
"'");
11679 int Pos = IDSet.Pos(
' ');
11690 CurrentID = IDSet.SubString(1, Pos - 1);
11691 IDSet = IDSet.SubString(Pos + 1, IDSet.Length() - Pos);
11703 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' is not an exit");
11710 if(!ExitList.empty())
11712 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
11714 if(*ELIT == VecPos)
11716 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' duplicates an earlier element");
11723 ExitList.push_back(VecPos);
11733 Pos = IDSet.Pos(
' ');
11740 int &Mass,
double &MaxBrakeRate,
double &PowerAtRail,
int &SignallerSpeed,
bool GiveMessages)
11747 AnsiString Remainder =
"";
11748 int SemiColonCount = 0;
11750 for(
int x = 1; x < TrainInfoStr.Length() + 1; x++)
11752 if(TrainInfoStr[x] ==
';')
11757 if((SemiColonCount != 6) && (SemiColonCount != 7) && (SemiColonCount != 1) && (SemiColonCount != 0))
11759 TimetableMessage(GiveMessages,
"Error in train information in '" + TrainInfoStr +
11760 "'. Should be headcode + optional description for a continuing service;" +
11761 " or headcode, description, start speed, max running speed, mass, brake force, power (and optional signaller max. speed) for a new service");
11765 if(SemiColonCount == 0)
11767 HeadCode = TrainInfoStr;
11776 if(SemiColonCount == 1)
11778 Pos = TrainInfoStr.Pos(
';');
11779 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
11780 Description = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
11786 if(Description ==
"")
11788 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
11792 if(Description.Length() > 60)
11794 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
11798 for(
int x = 1; x < Description.Length() + 1; x++)
11800 if((Description[x] <
' ') || (Description[x] >
'~'))
11802 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
11811 Pos = TrainInfoStr.Pos(
';');
11812 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
11813 Remainder = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
11819 Pos = Remainder.Pos(
';');
11820 Description = Remainder.SubString(1, Pos - 1);
11821 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11822 if(Description ==
"")
11824 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
11828 if(Description.Length() > 60)
11830 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
11834 for(
int x = 1; x < Description.Length() + 1; x++)
11836 if((Description[x] <
' ') || (Description[x] > 126))
11838 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
11843 Pos = Remainder.Pos(
';');
11844 AnsiString StartSpeedStr = Remainder.SubString(1, Pos - 1);
11846 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11847 if(StartSpeedStr ==
"")
11849 TimetableMessage(GiveMessages,
"Train starting speed missing in '" + TrainInfoStr +
"'");
11853 for(
int x = 1; x < StartSpeedStr.Length() + 1; x++)
11855 if((StartSpeedStr[x] <
'0') || (StartSpeedStr[x] >
'9'))
11857 TimetableMessage(GiveMessages,
"Train start speed contains invalid characters in '" + TrainInfoStr +
"'");
11862 StartSpeed = StartSpeedStr.ToInt();
11868 TimetableMessage(GiveMessages,
"Train starting speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
11872 Pos = Remainder.Pos(
';');
11873 AnsiString MaxRunningSpeedStr = Remainder.SubString(1, Pos - 1);
11875 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11876 if(MaxRunningSpeedStr ==
"")
11878 TimetableMessage(GiveMessages,
"Train maximum running speed missing in '" + TrainInfoStr +
"'");
11882 for(
int x = 1; x < MaxRunningSpeedStr.Length() + 1; x++)
11884 if((MaxRunningSpeedStr[x] <
'0') || (MaxRunningSpeedStr[x] >
'9'))
11886 TimetableMessage(GiveMessages,
"Train maximum running speed contains invalid characters in '" + TrainInfoStr +
"'");
11891 MaxRunningSpeed = MaxRunningSpeedStr.ToInt();
11897 TimetableMessage(GiveMessages,
"Train maximum running speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
11901 if(MaxRunningSpeed < 10)
11904 MaxRunningSpeed = 10;
11907 TimetableMessage(GiveMessages,
"Train maximum running speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
11911 Pos = Remainder.Pos(
';');
11912 AnsiString MassStr = Remainder.SubString(1, Pos - 1);
11914 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11917 TimetableMessage(GiveMessages,
"Train mass missing in '" + TrainInfoStr +
"'");
11921 for(
int x = 1; x < MassStr.Length() + 1; x++)
11923 if((MassStr[x] <
'0') || (MassStr[x] >
'9'))
11925 TimetableMessage(GiveMessages,
"Train mass contains invalid characters in '" + TrainInfoStr +
"'");
11930 Mass = MassStr.ToInt() * 1000;
11936 TimetableMessage(GiveMessages,
"Train mass > 10,000 tonnes in '" + TrainInfoStr +
"'. Setting it to 10,000 tonnes");
11942 TimetableMessage(GiveMessages,
"Train mass zero in '" + TrainInfoStr +
"'");
11946 Pos = Remainder.Pos(
';');
11947 AnsiString MaxBrakeForceStr = Remainder.SubString(1, Pos - 1);
11949 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11950 if(MaxBrakeForceStr ==
"")
11952 TimetableMessage(GiveMessages,
"Train braking force missing in '" + TrainInfoStr +
"'");
11956 for(
int x = 1; x < (MaxBrakeForceStr.Length() + 1); x++)
11958 if((MaxBrakeForceStr[x] !=
'.') && ((MaxBrakeForceStr[x] <
'0') || (MaxBrakeForceStr[x] >
'9')))
11960 TimetableMessage(GiveMessages,
"Train braking force contains invalid characters in '" + TrainInfoStr +
"'");
11965 double MaxBrakeForce = MaxBrakeForceStr.ToDouble() * 1000;
11968 if((MaxBrakeForce / Mass) > 1)
11970 MaxBrakeForce = Mass;
11973 TimetableMessage(GiveMessages,
"Train braking force too high in '" + TrainInfoStr +
"'. Setting it to the same as the train mass");
11977 if((MaxBrakeForce / Mass) < 0.01)
11979 MaxBrakeForce = Mass * 0.01;
11982 TimetableMessage(GiveMessages,
"Train braking force too low in '" + TrainInfoStr +
"'. Setting it to 1% of the train mass");
11987 MaxBrakeRate = MaxBrakeForce / Mass * 9.81;
11989 AnsiString GrossPowerStr =
"", SignallerSpeedStr =
"";
11991 if(SemiColonCount == 6)
11993 GrossPowerStr = Remainder;
11994 SignallerSpeedStr =
"30";
11998 Pos = Remainder.Pos(
';');
11999 GrossPowerStr = Remainder.SubString(1, Pos - 1);
12000 SignallerSpeedStr = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12003 if(GrossPowerStr ==
"")
12005 TimetableMessage(GiveMessages,
"Train power missing in '" + TrainInfoStr +
"'");
12009 for(
int x = 1; x < GrossPowerStr.Length() + 1; x++)
12011 if((GrossPowerStr[x] <
'0') || (GrossPowerStr[x] >
'9'))
12013 TimetableMessage(GiveMessages,
"Train power contains invalid characters in '" + TrainInfoStr +
"'");
12019 double GrossPower = GrossPowerStr.ToInt() * 1000;
12026 TimetableMessage(GiveMessages,
"Train power > 100,000kW in '" + TrainInfoStr +
"'. Setting it to 100,000kW");
12030 else if(GrossPower == 0)
12035 else if((GrossPower > 0) && (GrossPower < 10000))
12038 GrossPower = 10000;
12040 PowerAtRail = GrossPower * 0.8;
12044 if(SignallerSpeedStr ==
"")
12046 TimetableMessage(GiveMessages,
"Signaller speed not set in '" + TrainInfoStr +
"', either set a value or remove the extra semicolon");
12050 for(
int x = 1; x < SignallerSpeedStr.Length() + 1; x++)
12052 if((SignallerSpeedStr[x] <
'0') || (SignallerSpeedStr[x] >
'9'))
12054 TimetableMessage(GiveMessages,
"Signaller speed contains invalid characters in '" + TrainInfoStr +
"'");
12059 SignallerSpeed = SignallerSpeedStr.ToInt();
12065 TimetableMessage(GiveMessages,
"Signaller speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
12069 if(SignallerSpeed < 10)
12072 SignallerSpeed = 10;
12075 TimetableMessage(GiveMessages,
"Signaller speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
12093 if(OneEntry.Length() < 7)
12095 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
12099 int SemiColonCount = 0;
12101 for(
int x = 1; x < OneEntry.Length() + 1; x++)
12103 if(OneEntry[x] ==
';')
12108 if(SemiColonCount != 3)
12110 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
12114 if((OneEntry[1] !=
'R') || (OneEntry[2] !=
';'))
12116 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
12120 AnsiString Remainder = OneEntry.SubString(3, OneEntry.Length() - 2);
12125 Pos = Remainder.Pos(
';');
12126 AnsiString MinutesStr = Remainder.SubString(1, Pos - 1);
12128 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12129 if(MinutesStr ==
"")
12131 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute increment segment missing");
12135 if(MinutesStr.Length() > 3)
12138 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute value too high, maximum value is 999");
12142 for(
int x = 1; x < MinutesStr.Length() + 1; x++)
12144 if((MinutesStr[x] <
'0') || (MinutesStr[x] >
'9'))
12146 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in minute increment segment");
12151 RearStartOrRepeatMins = MinutesStr.ToInt();
12152 if(RearStartOrRepeatMins == 0)
12154 TimetableMessage(GiveMessages,
"Repeat minute increment is zero in: '" + OneEntry +
"' - can't have a zero value");
12158 Pos = Remainder.Pos(
';');
12159 AnsiString DigitsStr = Remainder.SubString(1, Pos - 1);
12161 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12162 if(DigitsStr ==
"")
12164 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - headcode increment segment missing");
12168 for(
int x = 1; x < DigitsStr.Length() + 1; x++)
12170 if((DigitsStr[x] <
'0') || (DigitsStr[x] >
'9'))
12172 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in headcode increment segment");
12177 if(DigitsStr.Length() > 2)
12179 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - maximum number of digits for headcode increment is 2");
12183 FrontStartOrRepeatDigits = DigitsStr.ToInt();
12197 "' - a repeating service with incrementing digits must have digits as its last two headcode characters");
12201 AnsiString NumberStr = Remainder;
12203 if(NumberStr ==
"")
12205 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - number of repeats missing");
12209 if(NumberStr.Length() > 4)
12212 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - repeat value too high, no timetabled event can exceed 95 hours & 59 minutes");
12216 for(
int x = 1; x < NumberStr.Length() + 1; x++)
12218 if((NumberStr[x] <
'0') || (NumberStr[x] >
'9'))
12221 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in number of repeats");
12226 NumberOfRepeats = NumberStr.ToInt();
12227 if(NumberOfRepeats == 0)
12229 TimetableMessage(GiveMessages,
"Number of repeats is zero in: '" + OneEntry +
"' - if no repeats are needed the repeat should be omitted");
12401 SecondPassMessage(GiveMessages,
"Error in timetable - there appear to be no train services in the timetable, it must contain at least one");
12420 TwoLocationFlag =
false;
12426 SecondPassMessage(GiveMessages,
"Error in timetable - the following service has no listed events, there must be at least one: " + TDEntry.
HeadCode);
12440 SecondPassMessage(GiveMessages,
"Error in timetable - service must have a start event and at least one other for: " + TDEntry.
HeadCode);
12456 "Error in timetable - a signaller control service can have no more than one item (a repeat) after the start event, see: " +
12468 "Error in timetable - a signaller control service cannot have any other than a repeat after the start event, see: " + TDEntry.
HeadCode);
12495 SecondPassMessage(GiveMessages,
"Error in timetable - finish events Fns-sh and Frh-sh not permitted immediately after an Snt entry for: " +
12506 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12511 SecondPassMessage(GiveMessages,
"Error in timetable - a start event is present that is not the first event for: " + TDEntry.
HeadCode);
12521 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12526 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat is present that is not the last item for: " + TDEntry.
HeadCode);
12536 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12547 SecondPassMessage(GiveMessages,
"Error in timetable - the last item must be either a finish event or a repeat for: " + TDEntry.
HeadCode);
12557 SecondPassMessage(GiveMessages,
"Error in timetable - the last event before the repeat must be a finish for: " + TDEntry.
HeadCode);
12569 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12576 SecondPassMessage(GiveMessages,
"Error in timetable - a finish event must be either the last or last but one for: " + TDEntry.
HeadCode);
12585 SecondPassMessage(GiveMessages,
"Error in timetable - the only event that can follow a finish event is a repeat for: " +
12605 if((AVEntry0.
Command ==
"Snt") || (AVEntry0.
Command ==
"Snt-sh"))
12607 AnsiString LocationName =
"";
12623 SecondPassMessage(GiveMessages,
"Error in timetable - stopped 'Snt' or 'Snt-sh' followed by an illegal event for: " +
12624 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
12633 SecondPassMessage(GiveMessages,
"Error in timetable - 'Snt' or 'Snt-sh' event at stop location but start speed not zero for: " +
12642 if(AVEntry0.
Command ==
"Snt-sh")
12656 SecondPassMessage(GiveMessages,
"Error in timetable - unlocated 'Snt' not followed by 'Fer', 'pas' or an arrival for: " +
12672 SecondPassMessage(GiveMessages,
"Error in timetable - 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' followed by an illegal event for: " +
12673 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
12684 bool FoundFlag =
false;
12690 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12702 SecondPassMessage(GiveMessages,
"Error in timetable - no location departure following an 'Sfs', 'Sns', 'Sns-sh'or 'Sns-fsh' event for: " +
12715 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12724 ": an event should have had a location name associated with it but it could not be found");
12730 for(
unsigned int z = y + 1; z <
TrainDataVector.at(x).ActionVector.size(); z++)
12752 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12762 SecondPassMessage(GiveMessages,
"Error in timetable - only a repeat can follow a finish entry for: " + TDEntry.
HeadCode);
12769 if(AVEntry.
Command ==
"F-nshs")
12774 SecondPassMessage(GiveMessages,
"Error in timetable - F-nshs (shuttle link) must be the last event for: " + TDEntry.
HeadCode);
12802 SecondPassMessage(GiveMessages,
"Error in timetable - a jbo event is followed by an illegal event for: " + TDEntry.
HeadCode +
12803 ". The event isn't valid for a stationary train.");
12813 SecondPassMessage(GiveMessages,
"Error in timetable - a train split can't be the last event for: " + TDEntry.
HeadCode);
12821 SecondPassMessage(GiveMessages,
"Error in timetable - a train split is followed by an illegal event for: " + TDEntry.
HeadCode +
12822 ". The event isn't valid for a stationary train.");
12840 SecondPassMessage(GiveMessages,
"Error in timetable - a 'cdt' is followed by an illegal event for: " + TDEntry.
HeadCode +
12841 ". The event isn't valid for a stationary train.");
12851 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure can't be the last event for: " + TDEntry.
HeadCode);
12859 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure is followed by an illegal event for: " +
12860 TDEntry.
HeadCode +
". The event isn't valid for a moving train.");
12878 SecondPassMessage(GiveMessages,
"Error in timetable - a pass time is followed by an illegal event for: " + TDEntry.
HeadCode +
12879 ". The event isn't valid for a moving train.");
12901 bool LastEntryIsAnArrival =
false;
12908 LastEntryIsAnArrival =
false;
12909 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12916 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
12918 if(LastEntryIsAnArrival)
12922 LastEntryIsAnArrival =
false;
12928 LastEntryIsAnArrival =
true;
12935 LastEntryIsAnArrival =
true;
12936 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12943 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
12945 if(LastEntryIsAnArrival)
12949 LastEntryIsAnArrival =
false;
12955 LastEntryIsAnArrival =
true;
12965 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12973 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival can't be the last event for: " + TDEntry.
HeadCode);
12981 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival is followed by an illegal event for: " + TDEntry.
HeadCode +
12982 ". The event isn't valid for a stationary train.");
12993 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure can't be the last event for: " + TDEntry.
HeadCode);
13001 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure is followed by an illegal event for: " + TDEntry.
HeadCode +
13002 ". The event isn't valid for a moving train.");
13016 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13023 throw Exception(
"Timetable error, TimeLoc entry has EventTime not -1 for " + TDEntry.
HeadCode);
13027 throw Exception(
"Timetable error, TimeLoc entry has neither arrival nor departure time set for " + TDEntry.
HeadCode);
13034 throw Exception(
"Timetable error, TimeTimeLoc entry has EventTime not -1 for " + TDEntry.
HeadCode);
13038 throw Exception(
"Timetable error, TimeTimeLoc entry has either arrival or departure time not set for " + TDEntry.
HeadCode);
13047 throw Exception(
"Timetable error, Cmd or PassTime entry has EventTime not set for " + TDEntry.
HeadCode);
13051 throw Exception(
"Timetable error, Cmd or PassTime entry has either arrival or departure time set for " + TDEntry.
HeadCode);
13058 throw Exception(
"Timetable error, Repeat entry has a time set for " + TDEntry.
HeadCode);
13069 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13084 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has a later arrival than departure time for: " +
13092 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has too early an arrival time for: " +
13107 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
13119 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
13131 SecondPassMessage(GiveMessages,
"Error in timetable - a train event has a time that is set too early for: " + TDEntry.
HeadCode +
13132 ", may be before timetable start time");
13143 AnsiString LastLocationName =
"";
13147 bool LastEntryIsAnArrival =
false;
13152 LastEntryIsAnArrival =
false;
13153 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
13154 if(LastLocationName !=
"")
13156 throw Exception(
"Timetable error, moving Snt entry has LocationName set for " + TDEntry.
HeadCode);
13158 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size();
13171 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
13183 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
13196 TwoLocationFlag =
true;
13201 LastEntryIsAnArrival =
false;
13205 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
13208 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
13213 else if(!LastEntryIsAnArrival && (AVEntry.
LocationName == LastLocationName))
13216 "Error in timetable - a location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode);
13222 LastEntryIsAnArrival = !LastEntryIsAnArrival;
13228 LastEntryIsAnArrival =
true;
13229 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
13230 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13242 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
13254 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
13267 TwoLocationFlag =
true;
13272 LastEntryIsAnArrival =
false;
13276 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
13279 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
13287 "A location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode +
". Please correct if this is an error.\n\nThis warning will not be shown again.");
13294 LastEntryIsAnArrival = !LastEntryIsAnArrival;
13302 AnsiString LocationNameToBeChecked =
"";
13307 unsigned int y = 0;
13321 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
13322 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
13340 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
13349 TwoLocationFlag =
true;
13360 if(TwoLocationFlag)
13370 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13375 throw Exception(
"Error, non- 'Snt', 'Fer' or Repeat entry doesn't have a location name set for " + TDEntry.
HeadCode);
13377 AnsiString LocName =
"";
13383 throw Exception(
"Error, 'Snt' entry at a stop location doesn't have a location name set for " + TDEntry.
HeadCode);
13390 throw Exception(
"Error, 'Snt' unlocated entry has a location name set for " + TDEntry.
HeadCode);
13413 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13438 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13460 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13482 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13501 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13504 if((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh"))
13519 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13524 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has FormatType unset for: " + TDEntry.
HeadCode);
13528 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has SequenceType unset for: " + TDEntry.
HeadCode);
13532 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has LocationType unset for: " + TDEntry.
HeadCode);
13536 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has ShuttleLinkType unset for: " + TDEntry.
HeadCode);
13575 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13577 AnsiString LocName =
TrainDataVector.at(x).ActionVector.at(y).LocationName;
13583 SecondPassMessage(GiveMessages,
"Error in timetable - continuation names (" + LocName +
") must not be included, see service " + HC);
13596 int IncMinutes = 0;
13606 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13612 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat time exceeds 95h 59m, see service " + HC);
13618 if((
double)
TrainDataVector.at(x).ActionVector.at(y).ArrivalTime > -1)
13623 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat entry time exceeds 95h 59m, see service " + HC);
13629 if((
double)
TrainDataVector.at(x).ActionVector.at(y).DepartureTime > -1)
13634 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat entry time exceeds 95h 59m, see service " + HC);
13647 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13673 (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"F-nshs"));
13681 if(HeadCode.Length() > 4)
13683 HeadCode = HeadCode.SubString(HeadCode.Length() - 3, 4);
13694 int ForwardCount = 0;
13695 int ReverseCount = 0;
13697 if(MainHeadCode == SecondHeadCode)
13699 SecondPassMessage(GiveMessages,
"Error in timetable - Service " + MainHeadCode +
" has an event that references itself");
13708 if(TDEntry.
HeadCode == MainHeadCode)
13710 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13725 if(ForwardCount == 0)
13728 throw Exception(
"Error, ForwardCount == 0 in CheckForDuplicateCrossReferences after called with found values");
13730 if(ForwardCount > 2)
13733 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + SecondHeadCode +
" from a train whose headcode is " +
13734 MainHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
13743 if(TDEntry.
HeadCode == SecondHeadCode)
13745 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13760 if(ReverseCount == 0)
13762 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + SecondHeadCode);
13767 if(ReverseCount > 2)
13770 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + MainHeadCode +
" from a train whose headcode is " +
13771 SecondHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
13776 if(ForwardCount != ReverseCount)
13778 SecondPassMessage(GiveMessages,
"Error in timetable - " + MainHeadCode +
" has a different number of references to " + SecondHeadCode +
13779 " than the other way round");
13810 int ForwardCount = 0;
13811 int ReverseCount = 0;
13812 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
13821 if(TDEntry.
HeadCode == MainHeadCode)
13823 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13826 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
13831 ForwardEntryPtr = &AVEntry;
13833 ForwardTDVectorNumber = x;
13836 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") ||
13837 (AVEntry.
Command ==
"Frh-sh")))
13842 ForwardEntryPtr = &AVEntry;
13844 ForwardTDVectorNumber = x;
13850 if(ForwardCount == 0)
13853 throw Exception(
"Error, ForwardCount == 0 in CheckCrossReferencesAndSetData after called with found values");
13855 if(ForwardCount > 1)
13857 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + OtherHeadCode +
" from a train whose headcode is " +
13867 if(TDEntry.
HeadCode == OtherHeadCode)
13869 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13872 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
13878 ReverseEntryPtr = &AVEntry;
13879 ReverseTDVectorNumber = x;
13882 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"Frh-sh")))
13888 ReverseEntryPtr = &AVEntry;
13889 ReverseTDVectorNumber = x;
13896 if(ReverseCount == 0)
13898 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + OtherHeadCode);
13903 if(ReverseCount > 1)
13905 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
13912 bool ForwardShuttleStart = ((ForwardEntryPtr->Command ==
"Sns-sh") || (ForwardEntryPtr->Command ==
"Snt-sh"));
13913 bool ForwardShuttleFinish = ((ForwardEntryPtr->Command ==
"Fns-sh") || (ForwardEntryPtr->Command ==
"Frh-sh"));
13914 bool ReverseShuttleStart = ((ReverseEntryPtr->
Command ==
"Sns-sh") || (ReverseEntryPtr->
Command ==
"Snt-sh"));
13915 bool ReverseShuttleFinish = ((ReverseEntryPtr->
Command ==
"Fns-sh") || (ReverseEntryPtr->
Command ==
"Frh-sh"));
13919 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat");
13926 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + OtherHeadCode +
" does not have a repeat");
13931 if(ForwardEntryPtr->LocationName ==
"")
13933 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
13934 ". One or other service does not have a location set");
13941 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
13942 ". One or other service does not have a location set");
13947 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
13949 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
13950 " is at a different location to the referencing train " + MainHeadCode);
13958 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
13960 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
13961 " has a different event time to the referencing train " + MainHeadCode);
13969 if(ForwardShuttleStart && ReverseShuttleFinish)
13974 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle service " + MainHeadCode +
13975 " first repeat restart time not consistent with finish service " + OtherHeadCode);
13981 if((ReverseEntryPtr->
Command ==
"Sfs") || (ReverseEntryPtr->
Command ==
"Sns"))
13984 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
13986 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' or 'Sns' event (" + OtherHeadCode +
13987 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
13993 if(ReverseEntryPtr->
Command ==
"Fjo")
13996 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
13998 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fjo' event (" + OtherHeadCode +
13999 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
14005 if(ReverseEntryPtr->
Command ==
"Fns")
14008 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
14010 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fns' event (" + OtherHeadCode +
14011 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
14017 if(ForwardEntryPtr->Command ==
"Sfs")
14019 if((ReverseEntryPtr->
Command !=
"fsp") && (ReverseEntryPtr->
Command !=
"rsp"))
14022 "Error in timetable - unable to find a corresponding split train event for the train that starts from a split whose headcode is " +
14029 if((ForwardEntryPtr->Command ==
"fsp") || (ForwardEntryPtr->Command ==
"rsp"))
14031 if(ReverseEntryPtr->
Command !=
"Sfs")
14033 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sfs' event for the train split whose headcode is " +
14043 SecondPassMessage(GiveMessages,
"Error in timetable - can't find timetabled location '" + ForwardEntryPtr->LocationName +
"' in railway - perhaps there are concourses without platforms?");
14050 SecondPassMessage(GiveMessages,
"Error in timetable - can't find any named location elements at '" + ForwardEntryPtr->LocationName +
"' - perhaps there are concourses without platforms?");
14057 SecondPassMessage(GiveMessages,
"Error in timetable - location too short to split a train at " + ForwardEntryPtr->LocationName);
14062 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
14073 if(ForwardEntryPtr->Command ==
"Sns")
14075 if(ReverseEntryPtr->
Command !=
"Fns")
14077 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fns' event for the 'Sns' train whose headcode is " +
14078 MainHeadCode +
" and is formed from a service with headcode " + OtherHeadCode);
14084 if(ForwardEntryPtr->Command ==
"Fns")
14086 if(ReverseEntryPtr->
Command !=
"Sns")
14088 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns' event for the train whose headcode is " + MainHeadCode +
14089 " and forms a new service with headcode " + OtherHeadCode);
14096 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
14107 if(ForwardEntryPtr->Command ==
"jbo")
14109 if(ReverseEntryPtr->
Command !=
"Fjo")
14111 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fjo' event for the train whose headcode is " + MainHeadCode +
14112 " and is joined by a train with headcode " + OtherHeadCode);
14118 if(ForwardEntryPtr->Command ==
"Fjo")
14120 if(ReverseEntryPtr->
Command !=
"jbo")
14122 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'jbo' event for the train whose headcode is " + MainHeadCode +
14123 " and joins a train with headcode " + OtherHeadCode);
14130 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
14140 if(ForwardShuttleStart)
14143 if(!ReverseShuttleFinish)
14146 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + MainHeadCode +
14147 " from train whose headcode is " + OtherHeadCode +
", has to be Fns-sh, Frh-sh");
14153 if(ReverseShuttleStart)
14156 if(!ForwardShuttleFinish)
14159 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + OtherHeadCode +
14160 " from train whose headcode is " + MainHeadCode +
", has to be Fns-sh, Frh-sh");
14167 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
14179 bool MainRepeat =
false, OtherRepeat =
false;
14189 OtherRepeat =
true;
14192 if((MainRepeat && !OtherRepeat) || (!MainRepeat && OtherRepeat))
14194 SecondPassMessage(GiveMessages,
"Error in timetable - only one repeat is provided for the train whose headcode is " + MainHeadCode +
14195 " and the associated train with headcode " + OtherHeadCode);
14200 if(MainRepeat && OtherRepeat)
14206 SecondPassMessage(GiveMessages,
"Error in timetable - repeat items don't correspond for the train whose headcode is " + MainHeadCode +
14207 " and the associated train with headcode " + OtherHeadCode);
14229 while(Input[1] ==
' ')
14231 if(Input.Length() > 1)
14233 Input = Input.SubString(2, Input.Length() - 1);
14247 while(Input[Input.Length()] ==
' ')
14249 if(Input.Length() > 1)
14251 Input = Input.SubString(1, Input.Length() - 1);
14261 AnsiString Output =
"";
14262 bool DelimiterFound =
false;
14264 for(
int x = 1; x < Input.Length() + 1; x++)
14268 if(Input[x] ==
' ')
14273 if((Input[x] !=
',') && (Input[x] !=
';'))
14275 DelimiterFound =
false;
14276 Output = Output + Input[x];
14280 DelimiterFound =
true;
14281 Output = Output + Input[x];
14293 DelimiterFound =
false;
14294 for(
int x = Input.Length(); x > 0; x--)
14298 if(Input[x] ==
' ')
14303 if((Input[x] !=
',') && (Input[x] !=
';'))
14305 DelimiterFound =
false;
14306 Output = AnsiString(Input[x]) + Output;
14310 DelimiterFound =
true;
14311 Output = AnsiString(Input[x]) + Output;
14336 if((AVEntry0.
Command !=
"Snt") && (AVEntry0.
Command !=
"Snt-sh"))
14338 throw Exception(
"Error, first entry not 'Snt' or 'Snt-sh' in IsSNTEntryLocated");
14350 LocationName = LocRear;
14354 LocationName = LocFront;
14356 if(LocationName ==
"")
14377 for(
unsigned int y = 0; y < TDEntry.
ActionVector.size(); y++)
14418 int RearPosition = 0, FrontPosition = 0, RearExitPos = 0;
14421 if(RearPosition < 0)
14428 if(FrontPosition < 0)
14439 for(
int x = 0; x < 4; x++)
14441 if(RearTrackElement.
Conn[x] == FrontPosition)
14456 TimetableMessage(GiveMessages,
"Front of train attempting to start on a continuation at: " + FrontElementStr);
14463 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + FrontElementStr);
14469 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + RearElementStr);
14474 if((RearType ==
Points) && (RearExitPos == 3))
14476 TimetableMessage(GiveMessages,
"Front of train attempting to start on element connected to diverging points at: " + RearElementStr);
14482 TimetableMessage(GiveMessages,
"Rear of train attempting to start on element connected to diverging points at: " + FrontElementStr);
14497 AnsiString(RearExitPos));
14508 int FrontPosition = RearTrackElement.
Conn[RearExitPos];
14510 int FrontEntryPos = RearTrackElement.
ConnLinkPos[RearExitPos];
14513 AnsiString RearName, FrontName;
14529 FrontName = FrontTrackElement.
ElementID;
14532 int LockedVectorNumber;
14702 "," + AnsiString(IncDigits));
14705 throw Exception(
"Error, last 2 characters not both digits and IncDigits > 0 in GetRepeatHeadCode");
14710 return(BaseHeadCode);
14712 int BaseDigits = BaseHeadCode.SubString(3, 2).ToInt();
14713 int NextRepeatDigits = BaseDigits + (IncDigits * RepeatNumber);
14715 while(NextRepeatDigits >= 100)
14717 NextRepeatDigits -= 100;
14719 AnsiString NextRepeatDigitsStr = AnsiString(NextRepeatDigits);
14721 if(NextRepeatDigitsStr.Length() < 2)
14723 NextRepeatDigitsStr = AnsiString(
'0') + NextRepeatDigitsStr;
14725 AnsiString NextRepeatHeadCode = BaseHeadCode.SubString(1, 2) + NextRepeatDigitsStr;
14728 return(NextRepeatHeadCode);
14736 AnsiString(RepeatNumber) +
"," + AnsiString(IncMinutes));
14737 TDateTime NextRepeatTime = BasicTime + TDateTime(((
double)(RepeatNumber * IncMinutes)) / 1440.0);
14739 return(NextRepeatTime);
14748 AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes));
14749 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
14750 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
14751 int RepeatSecs = RepeatMinutes * 60;
14753 if((ForwardSecs > (ReverseSecs - RepeatSecs + 10)) || (ForwardSecs < (ReverseSecs - RepeatSecs - 10)))
14788 NonRepeatingHeadCode);
14789 int ForwardCount = 0;
14790 int ReverseCount = 0;
14791 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
14801 if(TDEntry.
HeadCode == MainHeadCode)
14803 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14809 ForwardEntryPtr = &AVEntry;
14811 ForwardTDVectorNumber = x;
14816 if(ForwardCount == 0)
14819 throw Exception(
"Error, ForwardCount == 0 in CheckNonRepeatingShuttleLinksAndSetData after called with found values");
14821 if(ForwardCount > 1)
14823 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + NonRepeatingHeadCode +
" from a train whose headcode is " +
14833 if(TDEntry.
HeadCode == NonRepeatingHeadCode)
14835 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14842 ReverseEntryPtr = &AVEntry;
14843 ReverseTDVectorNumber = x;
14849 if(ReverseCount == 0)
14851 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + NonRepeatingHeadCode);
14856 if(ReverseCount > 1)
14858 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
14859 NonRepeatingHeadCode);
14864 if(((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh")) && (MainTrainDataPtr->
ActionVector.back().FormatType ==
Repeat))
14866 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle connecting train " + MainHeadCode +
" shouldn't have a repeat");
14871 if((ForwardEntryPtr->Command !=
"F-nshs") && (ForwardEntryPtr->Command !=
"Sns-fsh") && (MainTrainDataPtr->
ActionVector.back().FormatType !=
Repeat))
14873 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat item");
14878 if(ForwardEntryPtr->LocationName ==
"")
14880 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
14881 ". One or other service does not have a location set");
14888 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
14889 ". One or other service does not have a location set");
14894 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
14896 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + NonRepeatingHeadCode +
14897 " is at a different location to the referencing train " + MainHeadCode);
14902 if(ForwardEntryPtr->Command ==
"F-nshs")
14905 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
14907 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle in-link service " + MainHeadCode +
14908 " finish time not consistent with start time of shuttle service " + NonRepeatingHeadCode);
14914 if(ForwardEntryPtr->Command ==
"Fns-sh")
14918 MainTrainDataPtr->
ActionVector.back().RearStartOrRepeatMins, MainTrainDataPtr->
ActionVector.back().NumberOfRepeats))
14920 SecondPassMessage(GiveMessages,
"Error in timetable - service " + NonRepeatingHeadCode +
", which links out from shuttle service " + MainHeadCode +
14921 ", has the wrong start time. It should correspond to the finish time of the last shuttle.");
14927 if((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh"))
14930 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
14932 SecondPassMessage(GiveMessages,
"Error in timetable - the non repeating link service " + NonRepeatingHeadCode +
14933 " appears in the same sequence as the corresponding shuttle service " + MainHeadCode);
14951 if(ForwardEntryPtr->Command ==
"Sns-sh")
14953 if(ReverseEntryPtr->
Command !=
"F-nshs")
14955 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'F-nshs' event for the 'Sns-sh' train whose headcode is " +
14956 MainHeadCode +
" and is a new shuttle service formed from the service with headcode " + NonRepeatingHeadCode);
14962 if(ForwardEntryPtr->Command ==
"F-nshs")
14964 if(ReverseEntryPtr->
Command !=
"Sns-sh")
14966 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns-sh' event for the 'F-nshs' train whose headcode is " +
14967 MainHeadCode +
" and forms a new shuttle service with headcode " + NonRepeatingHeadCode);
14974 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
14985 if(ForwardEntryPtr->Command ==
"Sns-fsh")
14987 if(ReverseEntryPtr->
Command !=
"Fns-sh")
14990 "Error in timetable - unable to find a corresponding 'Fns-sh' event for the 'Sns-fsh' non-shuttle service whose headcode is " + MainHeadCode +
14991 " formed from a shuttle service with headcode " + NonRepeatingHeadCode);
14997 if(ForwardEntryPtr->Command ==
"Fns-sh")
14999 if(ReverseEntryPtr->
Command !=
"Sns-fsh")
15002 "Error in timetable - unable to find a corresponding 'Sns-fsh' event for the 'Fns-sh' shuttle service whose headcode is " + MainHeadCode +
15003 " and forms a new non-shuttle service with headcode " + NonRepeatingHeadCode);
15010 ForwardEntryPtr->NonRepeatingShuttleLinkEntryPtr = OtherTrainDataPtr;
15034 +
"," + AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes) +
"," + AnsiString(RepeatNumber));
15035 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
15036 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
15037 int RepeatSecs = RepeatMinutes * RepeatNumber * 60;
15039 if((ReverseSecs > (ForwardSecs + RepeatSecs + 10)) || (ReverseSecs < (ForwardSecs + RepeatSecs - 10)))
15063 throw Exception(
"Error - last entry in " + TDEntryPtr->
HeadCode +
" service is not a repeat - should have already found this error");
15066 AnsiString OriginalHeadCode = TDEntryPtr->
HeadCode;
15067 AnsiString LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
15069 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
15071 SecondPassMessage(GiveMessages,
"Error in timetable - last event in shuttle service " + TDEntryPtr->
HeadCode +
" is not 'Fns', 'Fns-sh' or 'Frh-sh'");
15076 while(LastActionCommand ==
"Fns")
15078 TDEntryPtr = (TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr;
15079 LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
15080 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
15083 "Error in timetable - last event in a continuation shuttle service (i.e links back to a shuttle) whose headcode is " + TDEntryPtr->
HeadCode +
15084 " is not 'Fns', 'Fns-sh' or 'Frh-sh'");
15091 if((TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr != ShuttleStartAddress)
15094 " is a shuttle finish, but it doesn't link back to the start of the original shuttle starting service " + OriginalHeadCode +
15095 ". The linking of two or more shuttles is not permitted.");
15115 ShowMessage(Message);
15133 ShowMessage(Message);
15172 AnsiString(ActionEventType) +
"," + LocationID);
15173 AnsiString BaseLog =
"", Prefix =
"", ErrorLog =
"", WarningStr =
"";
15178 Prefix =
" ERROR: ";
15181 Prefix =
" HELD: ";
15182 ErrorLog =
" can't enter railway, train obstructing entry position ";
15183 WarningStr =
" can't enter railway, train obstructing entry position ";
15188 Prefix =
" HELD: ";
15189 ErrorLog =
" can't enter railway, route set against it at entry position ";
15190 WarningStr =
" can't enter railway, route set against it at entry position ";
15195 Prefix =
" HELD: ";
15196 ErrorLog =
" can't be created, train obstructing ";
15197 WarningStr =
" can't be created, train obstructing ";
15202 Prefix =
" HELD: ";
15203 ErrorLog =
" can't be created on a locked route at ";
15204 WarningStr =
" can't be created on a locked route at ";
15209 Prefix =
" HELD: ";
15210 ErrorLog =
" can't enter on a locked route at ";
15211 WarningStr =
" can't enter on a locked route at ";
15216 Prefix =
" HELD: ";
15217 ErrorLog =
" can't be created, diverging points at ";
15218 WarningStr =
" can't be created, diverging points at ";
15223 ErrorLog =
" left railway unexpectedly at ";
15228 ErrorLog =
" left railway at an incorrect exit at ";
15233 ErrorLog =
" failed to split - location too short at ";
15234 WarningStr =
" failed to split, location too short at ";
15239 Prefix =
" HELD: ";
15240 ErrorLog =
" unable to split - other train obstructing at ";
15241 WarningStr =
" unable to split - other train obstructing at ";
15246 ErrorLog =
" stopped at buffers unexpectedly at position ";
15250 ErrorLog =
" failed to stop at ";
15255 ErrorLog =
" failed to split at ";
15260 ErrorLog =
" failed to be joined by other train at ";
15265 ErrorLog =
" failed to join other train at ";
15270 ErrorLog =
" failed to terminate at ";
15275 ErrorLog =
" failed to form new service at ";
15280 ErrorLog =
" failed to exit railway ";
15285 ErrorLog =
" failed to change direction at ";
15290 ErrorLog =
" failed to pass ";
15295 ErrorLog =
" facing buffers and unable to start at ";
15299 ErrorLog =
" DERAILED at position ";
15300 Prefix =
" DERAILMENT: ";
15305 ErrorLog =
" CRASHED INTO BUFFERS at ";
15306 Prefix =
" CRASH: ";
15311 ErrorLog =
" CRASHED INTO ROAD TRAFFIC AT A LEVEL CROSSING at ";
15312 Prefix =
" CRASH: ";
15317 ErrorLog =
" CRASHED INTO " + OtherHeadCode +
" at position ";
15318 Prefix =
" CRASH: ";
15322 else if(ActionEventType ==
FailSPAD)
15324 ErrorLog =
" PASSED SIGNAL AT DANGER at position ";
15325 Prefix =
" SPAD: ";
15330 ErrorLog =
"Signals reset ahead of train, route cancelled at position ";
15331 Prefix =
" SPAD RISK: ";
15336 ErrorLog =
" forced a route cancellation by occupying it incorrectly at ";
15340 Prefix =
" WARNING: ";
15341 ErrorLog =
" waiting to join " + OtherHeadCode +
" at ";
15342 WarningStr =
" waiting to join " + OtherHeadCode +
" at ";
15347 Prefix =
" WARNING: ";
15348 ErrorLog =
" waiting to be joined by " + OtherHeadCode +
" at ";
15349 WarningStr =
" waiting to be joined by " + OtherHeadCode +
" at ";
15387 std::ofstream OutFile(
"TrainData.csv");
15391 ShowMessage(
"Output file TrainData.csv failed to open");
15398 OutFile <<
"HeadCode" <<
',' <<
"Description" <<
',' <<
"StartSpeed" <<
',' <<
"MaxRunningSpeed" <<
',' <<
"NumberOfTrains" <<
'\n' <<
'\n';
15403 OutFile <<
',' <<
"FormatType" <<
',' <<
"EventTime" <<
',' <<
"ArrivalTime" <<
',' <<
"DepartureTime" <<
',' <<
"LocationName" <<
',' <<
"Command" <<
15404 ',' <<
"OtherHeadCode" <<
',' <<
"LinkedTrainEntryPtr" <<
',' <<
"RearStartOrRepeatMins" <<
',' <<
"FrontStartOrRepeatDigits" <<
',' <<
15405 "RepeatNumber" <<
'\n' <<
'\n';
15406 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15409 AnsiString TimetableEntryTypeStr;
15415 TimetableEntryTypeStr =
"NoFormat";
15421 TimetableEntryTypeStr =
"TimeLoc";
15427 TimetableEntryTypeStr =
"TimeTimeLoc";
15433 TimetableEntryTypeStr =
"TimeCmd";
15439 TimetableEntryTypeStr =
"StartNew";
15445 TimetableEntryTypeStr =
"TimeCmdHeadCode";
15451 TimetableEntryTypeStr =
"FinRemHere";
15457 TimetableEntryTypeStr =
"FNSShuttle";
15463 TimetableEntryTypeStr =
"SNTShuttle";
15469 TimetableEntryTypeStr =
"SNSShuttle";
15475 TimetableEntryTypeStr =
"SNSNonRepeatFromShuttle";
15481 TimetableEntryTypeStr =
"FSHNewService";
15487 TimetableEntryTypeStr =
"Repeat";
15493 TimetableEntryTypeStr =
"Default";
15504 OutFile <<
',' <<
',' <<
"Mass" <<
',' <<
"MaxBrakeRate" <<
',' <<
"PowerAtRail" <<
',' <<
"TrainID" <<
',' <<
"RunningEntry" <<
'\n' <<
'\n';
15505 for(
unsigned int y = 0; y <
TrainDataVector.at(x).TrainOperatingDataVector.size(); y++)
15508 AnsiString RunningEntryStr;
15514 RunningEntryStr =
"NotStarted";
15520 RunningEntryStr =
"Running";
15526 RunningEntryStr =
"Exited";
15530 OutFile <<
',' <<
',' << TOD.
TrainID <<
',' << RunningEntryStr.c_str() <<
',' <<
'\n';
15547 ShowMessage(Message);
15548 BaseTime = TDateTime::CurrentDateTime();
15562 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
15575 TTrain *NewTrain =
new TTrain(1, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
15577 for(
int x = 0; x < NumberOfTrains; x++)
15579 *NewTrain =
TTrain(2, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
15599 int NumberOfTrains;
15606 for(
int x = 0; x < NumberOfTrains; x++)
15643 for(
int x = 0; x < LockedRouteVectorSize; x++)
15650 LockedRouteObject.
LockStartTime = TDateTime(LockStartTimeDouble);
15661 int LockedRouteVectorSize;
15668 for(
int x = 0; x < LockedRouteVectorSize; x++)
15726 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
15734 ContinuationAutoSigObject.
PassoutTime = TDateTime(PassoutTimeDouble);
15745 int ContinuationAutoSigVectorSize;
15752 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
15822 if(AVFirstEntry.
Command ==
"Snt")
15846 CTEMMP.second = CTEEntry;
15853 throw Exception(
"Error, Last ActionVectorEntry not a repeat in BuildContinuationTrainExpectationMultiMap");
15861 CTEMMP.second = CTEEntry;
15882 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
15899 if((VecPos < 0) || (VecPos >= (
int)
TrainVector.size()))
15901 throw Exception(
"Out of Range Error, vector size: " + AnsiString(
TrainVector.size()) +
", VecPos: " + AnsiString(VecPos) +
" in TrainVectorAt");
15912 AnsiString RetStr =
"", PartStr =
"";
16027 AnsiString TTFileName = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
16031 TTFileName = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
16033 AnsiString ShortTTName =
"";
16035 for(
int x = TTFileName.Length(); x > 0; x--)
16037 if(TTFileName[x] ==
'\\')
16039 ShortTTName = TTFileName.SubString(x + 1, TTFileName.Length() - x - 4);
16044 ShowMessage(
"Creates two timetables named " + ShortTTName +
16045 " in the 'Formatted timetables' folder, one in service order in '.csv' format, and one in chronological order in '.txt' format");
16047 Screen->Cursor = TCursor(-11);
16049 AnsiString FormatNoDPStr =
"#######0";
16050 AnsiString TableTitle =
"", TimetableTimeStr =
"", MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"", FirstHeadCode =
"", Header =
"";
16053 TableTitle =
"Railway: " + RailwayTitle +
"; Timetable: " + TimetableTitle +
"; Start time: " + TimetableTimeStr;
16060 MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"";
16062 if(TrainDataEntry.
Mass > 0)
16064 MassStr =
"; Mass " + AnsiString::FormatFloat(FormatNoDPStr, ((
double)TrainDataEntry.
Mass) / 1000) +
"Te; ";
16068 PowerStr =
"Power " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
PowerAtRail / 1000 / 0.8) +
"kW; ";
16072 BrakeStr =
"Brake force " + AnsiString::FormatFloat(FormatNoDPStr, (TrainDataEntry.
MaxBrakeRate * TrainDataEntry.
Mass / 9810)) +
"Te; ";
16076 MaxSpeedStr =
"Maximum speed " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
MaxRunningSpeed) +
" km/h";
16078 FirstHeadCode = TrainDataEntry.
HeadCode;
16079 int IncDigits = 0, IncMinutes = 0;
16081 if(!ActionVector.empty())
16083 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
16085 IncDigits = ActionVector.at(ActionVector.size() - 1).FrontStartOrRepeatDigits;
16086 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
16094 if((TrainDataEntry.
Description !=
"") && (MassStr !=
""))
16096 OneTTLine.
Header = TrainDataEntry.
Description + MassStr + PowerStr + BrakeStr + MaxSpeedStr;
16104 for(
unsigned int z = 0; z < ActionVector.size(); z++)
16109 AnsiString PartStr =
"", TimeStr =
"";
16126 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
16130 PartStr =
"Created at " + ActionVectorEntry.
LocationName;
16140 PartStr =
"Enters at " + LocName;
16153 PartStr =
"Created at " + LocName;
16167 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
16172 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
16178 else if(ActionVectorEntry.
Command ==
"Sfs")
16180 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" split from";
16184 else if(ActionVectorEntry.
Command ==
"Sns")
16186 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
16194 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
16200 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
16208 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
16211 AnsiString FirstHeadCode = TDE->
HeadCode;
16215 TimeStr =
GetRepeatHeadCode(36, FirstHeadCode, LastRepeatNumber, IncrementalDigits) +
" at " +
16227 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
16229 OneTTEntry.
Action = PartStr;
16230 OneTTEntry.
Time = TimeStr;
16232 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
16237 PartStr =
"Arrives & departs " + ActionVectorEntry.
LocationName;
16243 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
16248 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
16256 else if(ActionVectorEntry.
Command ==
"jbo")
16258 PartStr =
"Joined at " + ActionVectorEntry.
LocationName +
" by";
16262 else if(ActionVectorEntry.
Command ==
"fsp")
16264 PartStr =
"Splits from front at " + ActionVectorEntry.
LocationName +
" to form";
16268 else if(ActionVectorEntry.
Command ==
"rsp")
16270 PartStr =
"Splits from rear at " + ActionVectorEntry.
LocationName +
" to form";
16274 else if(ActionVectorEntry.
Command ==
"cdt")
16276 PartStr =
"Changes direction at " + ActionVectorEntry.
LocationName;
16282 if(ActionVectorEntry.
Command ==
"Fns")
16284 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
16288 else if(ActionVectorEntry.
Command ==
"F-nshs")
16290 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
16296 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service ";
16303 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
16309 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
16316 PartStr =
"Terminates shuttle service at " + ActionVectorEntry.
LocationName;
16321 else if(ActionVectorEntry.
Command ==
"Frh")
16323 PartStr =
"Terminates at " + ActionVectorEntry.
LocationName;
16328 if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
16332 else if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
16342 else if(ActionVectorEntry.
Command ==
"Fer")
16344 AnsiString AllowedExits;
16348 else if(ActionVectorEntry.
Command ==
"Fjo")
16350 PartStr =
"At " + ActionVectorEntry.
LocationName +
" joins";
16359 OneTTEntry.
Action = PartStr;
16360 OneTTEntry.
Time = TimeStr;
16367 AllTTTrains->push_back(OneTTLine);
16371 std::ofstream TTFile(TTFileName.c_str());
16375 StopTTClockMessage(64,
"Formatted timetable file failed to open - can't be created");
16376 delete AllTTTrains;
16411 TTFile << TableTitle.c_str() <<
'\n' <<
'\n';
16412 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
16414 TTFile << AllTTTrains->at(x).Header.c_str();
16417 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
16419 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
16421 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str() <<
',';
16425 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str();
16428 TTFile <<
'\n' <<
'\n';
16430 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.size(); z++)
16432 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.at(z).Action.c_str() <<
',';
16433 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
16435 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
16437 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str() <<
',';
16441 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str();
16446 TTFile <<
'\n' <<
'\n';
16451 AnsiString TTFileName2 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
16453 TTFileName2 = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName2 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".txt";
16455 std::ofstream TTFile2(TTFileName2.c_str());
16459 StopTTClockMessage(67,
"Chronological timetable file failed to open - can't be created");
16460 delete AllTTTrains;
16464 typedef std::multimap<AnsiString, AnsiString>TAnsiMultiMap;
16465 std::multimap<AnsiString, AnsiString>::iterator AMMIT;
16466 std::pair<AnsiString, AnsiString>AnsiMultiMapEntry;
16468 TAnsiMultiMap *TAMM =
new TAnsiMultiMap;
16473 TTFile2 << TableTitle.c_str() <<
'\n' <<
'\n';
16474 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
16476 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
16478 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.size(); z++)
16480 bool GiveMessagesFalse =
false;
16481 AnsiString TimeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time;
16482 AnsiString HeadCodeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode;
16483 AnsiString ActionString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Action;
16488 AnsiString OtherHeadCode = TimeString.SubString(1, 4);
16489 TimeString = TimeString.SubString(9, 5);
16490 ActionString +=
" " + OtherHeadCode;
16492 if(TimeString.SubString(1, 7) ==
"End at ")
16495 TimeString = TimeString.SubString(8, 5);
16497 AnsiString OneLine = TimeString +
' ' + HeadCodeString +
' ' + ActionString +
'\n';
16498 AnsiMultiMapEntry.first = TimeString;
16499 AnsiMultiMapEntry.second = OneLine;
16500 TAMM->insert(AnsiMultiMapEntry);
16505 for(AMMIT = TAMM->begin(); AMMIT != TAMM->end(); AMMIT++)
16507 TTFile2 << (AMMIT->second).c_str();
16509 delete AllTTTrains;
16518 bool AtLocChecked,
bool DirChecked,
int ArrRange,
int DepRange)
16522 bool AnalysisError =
false;
16523 AnsiString SequenceLog =
"SequenceLog\n";
16565 TTrainDataVector::iterator TDVIt, TDVCopyIt;
16567 int IteratorNumber = 0;
16568 AnsiString AnsiSuffix =
"";
16573 for(TDVCopyIt = TrainDataVectorCopy.begin() + IteratorNumber; TDVCopyIt != TrainDataVectorCopy.end(); TDVCopyIt++)
16575 if(TDVCopyIt->ServiceReference == TDVIt->ServiceReference)
16578 AnsiSuffix = AnsiString(Suffix);
16579 TDVCopyIt->ServiceReference = TDVIt->ServiceReference +
"/" + AnsiSuffix;
16583 SequenceLog +=
"1\n";
16586 std::pair<AnsiString, TServiceCallingLocsList> AllServiceCallingLocsEntry;
16587 for(
unsigned int x = 0; x < TrainDataVectorCopy.size(); x++)
16592 ServiceCallingLocsList.clear();
16593 if(ActionVector.empty())
16597 if(ActionVector.at(0).SignallerControl)
16601 for(
unsigned int z = 0; z < ActionVector.size(); z++)
16619 int HLoc = TE.
HLoc;
16620 int VLoc = TE.
VLoc;
16621 AnsiString HString;
16622 AnsiString VString;
16625 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
16629 HString = AnsiString(HLoc);
16633 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
16637 VString = AnsiString(VLoc);
16639 ServiceCallingLocsList.push_back(HString +
'-' + VString);
16662 else if(AVE.
Command ==
"cdt")
16664 if(ActionVector.at(z-1).SequenceType ==
Start)
16668 else if(ActionVector.at(z+1).SequenceType ==
Finish)
16675 ServiceCallingLocsList.push_back(
"%%%" + TimeString);
16684 ServiceCallingLocsList.push_back(LName);
16688 int HLoc = TE.
HLoc;
16689 int VLoc = TE.
VLoc;
16690 AnsiString HString;
16691 AnsiString VString;
16694 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
16698 HString = AnsiString(HLoc);
16702 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
16706 VString = AnsiString(VLoc);
16708 ServiceCallingLocsList.push_back(HString +
'-' + VString);
16712 AllServiceCallingLocsEntry.second = ServiceCallingLocsList;
16716 SequenceLog +=
"2\n";
16746 ShowMessage(
"Unable to create a program-readable timetable - please check the timetable file validity");
16752 bool NumPlatsAtThisLocCalculated =
false, ArrivalsPrinted =
false, DeparturesPrinted =
false, AtLocsPrinted =
false;
16753 AnsiString PreviousService =
"", PreviousServiceAndRepeatNumTotalOutput =
"", BasicTime =
"", MinuteString =
"", LastAnsiTime =
"";
16754 int NumTrains = 0, NumPlats = 0, LastFrhCount = 0, FrhCount = 0, NumTrainsAtLoc = 0;
16756 SequenceLog +=
"3\n";
16758 for(
unsigned int x = 0; x < TrainDataVectorCopy.size(); x++)
16763 TDateTime LastTDTime;
16764 int IncMinutes = 0;
16766 if(ActionVector.empty())
16770 if(ActionVector.at(0).SignallerControl)
16774 if(AVLast->FormatType ==
Repeat)
16776 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
16784 if(AVLast->ArrivalTime != TDateTime(-1))
16786 LastTDTime = AVLast->ArrivalTime;
16788 else if(AVLast->EventTime != TDateTime(-1))
16790 LastTDTime = AVLast->EventTime;
16809 SequenceLog +=
"4\n";
16841 for(
unsigned int x = 0; x < TrainDataVectorCopy.size(); x++)
16846 int IncMinutes = 0;
16848 if(ActionVector.empty())
16852 if(ActionVector.at(0).SignallerControl)
16856 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
16858 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
16860 for(
int y = 0; y < NumTrains; y++)
16874 for(
unsigned int z = 0; z < ActionVector.size(); z++)
16889 LocServiceTimesVector.push_back(TLSTEntry);
16892 AnsiString IncTime =
"", FoundStopTime =
"";
16893 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
16895 if(ActionVector.at(a).FormatType ==
TimeLoc)
16900 if(ActionVector.at(a).SequenceType ==
Finish)
16906 if(FoundStopTime ==
"")
16908 throw Exception(
"Failure to determine FoundStopTime for located Snt");
16910 int WhileCount = 0;
16919 if(IncTime >= FoundStopTime)
16923 LocServiceTimesVector.push_back(TLSTEntry);
16924 if(WhileCount > 2000)
16926 throw Exception(
"While loop failed to break in 2000 loops for located Snt");
16939 int HLoc = TE.
HLoc;
16940 int VLoc = TE.
VLoc;
16941 AnsiString HString;
16942 AnsiString VString;
16945 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
16949 HString = AnsiString(HLoc);
16953 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
16957 VString = AnsiString(VLoc);
16959 TLSTEntry.
Location = HString +
'-' + VString;
16963 LocServiceTimesVector.push_back(TLSTEntry);
16971 LocServiceTimesVector.push_back(TLSTEntry);
16973 AnsiString IncTime =
"", FoundStopTime =
"";
16974 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
16976 if(ActionVector.at(a).FormatType ==
TimeLoc)
16981 if(ActionVector.at(a).SequenceType ==
Finish)
16987 if(FoundStopTime ==
"")
16989 throw Exception(
"Failure to determine FoundStopTime for SequenceType == Start");
16991 int WhileCount = 0;
17000 if(IncTime >= FoundStopTime)
17004 LocServiceTimesVector.push_back(TLSTEntry);
17005 if(WhileCount > 2000)
17007 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == Start");
17017 bool SkipAddingMinutes =
false;
17020 LocServiceTimesVector.push_back(TLSTEntry);
17022 AnsiString IncTime =
"", FoundStopTime =
"";
17023 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
17025 if(ActionVector.at(a).FormatType ==
TimeLoc)
17030 if(ActionVector.at(a).SequenceType ==
Finish)
17033 if((a <= (z + 2)) && (FoundStopTime == TLSTEntry.
ArrTime) && ((ActionVector.at(a).LinkedTrainEntryPtr > 0) || (ActionVector.at(a).NonRepeatingShuttleLinkEntryPtr > 0)))
17037 LocServiceTimesVector.pop_back();
17038 SkipAddingMinutes =
true;
17043 if(FoundStopTime ==
"")
17045 throw Exception(
"Failure to determine FoundStopTime for SequenceType == Start");
17047 if(!SkipAddingMinutes)
17049 int WhileCount = 0;
17058 if(IncTime >= FoundStopTime)
17062 LocServiceTimesVector.push_back(TLSTEntry);
17063 if(WhileCount > 2000)
17065 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == Start");
17074 if((TLSTEntry.
Location == LocServiceTimesVector.back().Location) && (TLSTEntry.
ServiceAndRepeatNum == LocServiceTimesVector.back().ServiceAndRepeatNum))
17076 if(TLSTEntry.
DepTime == LocServiceTimesVector.back().ArrTime)
17078 TLSTEntry.
ArrTime = LocServiceTimesVector.back().ArrTime;
17079 LocServiceTimesVector.pop_back();
17080 LocServiceTimesVector.push_back(TLSTEntry);
17085 LocServiceTimesVector.push_back(TLSTEntry);
17091 LocServiceTimesVector.push_back(TLSTEntry);
17110 LocServiceTimesVector.push_back(TLSTEntry);
17114 AnsiString TempDepTime = TLSTEntry.
DepTime;
17116 LocServiceTimesVector.push_back(TLSTEntry);
17118 while(TLSTEntry.
AtLocTime < TempDepTime)
17123 TLSTEntry.
DepTime = TempDepTime;
17124 LocServiceTimesVector.push_back(TLSTEntry);
17128 LocServiceTimesVector.push_back(TLSTEntry);
17139 LocServiceTimesVector.push_back(TLSTEntry);
17142 LocServiceTimesVector.push_back(TLSTEntry);
17159 AnsiString HString;
17160 AnsiString VString;
17163 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
17167 HString = AnsiString(HLoc);
17171 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
17175 VString = AnsiString(VLoc);
17177 TLSTEntry.
Location = HString +
'-' + VString;
17179 LocServiceTimesVector.push_back(TLSTEntry);
17184 AnsiString FrhTime;
17185 if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
17189 else if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
17197 LocServiceTimesVector.push_back(TLSTEntry);
17203 LocServiceTimesVector.push_back(TLSTEntry);
17208 else if(AVE.
Command ==
"Frh-sh")
17210 if(y == NumTrains - 1)
17216 LocServiceTimesVector.push_back(TLSTEntry);
17222 LocServiceTimesVector.push_back(TLSTEntry);
17235 SequenceLog +=
"5\n";
17263 TLocServiceTimesVector::iterator Ptr1, Ptr2;
17266 AnsiString TTFileName3 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
17267 TTFileName3 = CurDir +
"\\Formatted timetables\\Conflict Analysis " + TTFileName3 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
17269 std::ofstream TTFile3(TTFileName3.c_str());
17273 ShowMessage(
"Conflict Analysis file failed to open - can't be created");
17277 if(LocServiceTimesVector.empty())
17279 ShowMessage(
"No timetabled services found");
17281 DeleteFile(TTFileName3);
17285 TTFile3 <<
"Timetable analysis for timetable: '" + TimetableTitle +
"' in conjunction with railway: '" + RailwayTitle +
"'\n";
17286 TTFile3 <<
"See user manual or on-screen help section 5.12 for detailed information.\n\n\n";
17287 SequenceLog +=
"6\n";
17336 Ptr1 = LocServiceTimesVector.begin();
17338 while(Ptr2 != LocServiceTimesVector.end())
17340 while(Ptr2->Location == Ptr1->Location)
17343 if(Ptr2 == LocServiceTimesVector.end())
17350 if(Ptr2 != LocServiceTimesVector.end())
17358 TTFile3 <<
"Arrival & pass analysis: an asterisk means that the number of same approach code arrivals and passes is equal to or greater than the number of platforms.\n";
17359 TTFile3 <<
"If the total number of arrivals and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
17360 MinuteString =
" minutes";
17361 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
17364 MinuteString =
" minute";
17366 TTFile3 <<
"Location,Number of,Number of,Services arriving within " << AnsiString(ArrRange) << MinuteString <<
" with their arrival times and approach codes\n";
17367 TTFile3 <<
",Platforms,Trains\n\n";
17369 Ptr1 = LocServiceTimesVector.begin();
17371 while(Ptr2 != LocServiceTimesVector.end())
17373 PreviousService =
"";
17374 NumTrainsAtLoc = 0;
17375 ServiceAndRepeatNumTotal =
"";
17377 NumPlatsAtThisLocCalculated =
false;
17379 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
17381 PreviousService =
"";
17382 NumTrainsAtLoc = 0;
17383 ServiceAndRepeatNumTotal =
"";
17385 NumPlatsAtThisLocCalculated =
false;
17389 if(Ptr2 == LocServiceTimesVector.end())
17394 if(Ptr2 == LocServiceTimesVector.end())
17398 while(Ptr2->Location == Ptr1->Location)
17400 PreviousService =
"";
17401 NumTrainsAtLoc = 0;
17402 ServiceAndRepeatNumTotal =
"";
17403 BasicTime = Ptr1->ArrTime;
17404 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
17408 while(!
WithinTimeRange(0, BasicTime, Ptr2->ArrTime, ArrRange) || ((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
"")))
17410 BasicTime = Ptr2->ArrTime;
17413 if(Ptr2 == LocServiceTimesVector.end())
17417 if(Ptr2->Location != Ptr1->Location)
17422 if(Ptr2 == LocServiceTimesVector.end())
17426 if(Ptr2->Location != Ptr1->Location)
17432 if((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
""))
17436 if(!NumPlatsAtThisLocCalculated)
17439 NumPlatsAtThisLocCalculated =
true;
17441 if(Ptr1->ServiceAndRepeatNum != PreviousService)
17443 if(ServiceAndRepeatNumTotal ==
"")
17445 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
17446 NumTrainsAtLoc = 1;
17450 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
17453 PreviousService = Ptr2->ServiceAndRepeatNum;
17454 if(ServiceAndRepeatNumTotal ==
"")
17456 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
17457 NumTrainsAtLoc = 1;
17461 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
17465 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(2, BasicTime, Ptr2->ArrTime, ArrRange)))
17467 int MaxNumberOfSameDirections = 0;
17468 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
true, AnalysisError, MaxNumberOfSameDirections);
17473 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
17477 AnsiString Asterisk =
"";
17478 if(MaxNumberOfSameDirections >= NumPlats)
17483 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
17484 ArrivalsPrinted =
true;
17485 ServiceAndRepeatNumTotal =
"";
17487 if(Ptr2 == LocServiceTimesVector.end())
17491 if(Ptr2->Location != Ptr1->Location)
17496 if(Ptr2 == LocServiceTimesVector.end())
17502 if(!ArrivalsPrinted)
17504 TTFile3 <<
"Nothing to report for arrivals";
17509 SequenceLog +=
"7\n";
17514 Ptr1 = LocServiceTimesVector.begin();
17516 while(Ptr2 != LocServiceTimesVector.end())
17518 while(Ptr2->Location == Ptr1->Location)
17521 if(Ptr2 == LocServiceTimesVector.end())
17528 if(Ptr2 != LocServiceTimesVector.end())
17535 TTFile3 <<
"Departure & pass analysis: an asterisk means that the number of same exit code departures and passes is equal to or greater than the number of platforms.\n";
17536 TTFile3 <<
"If the total number of departures and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
17537 MinuteString =
" minutes";
17538 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
17541 MinuteString =
" minute";
17543 TTFile3 <<
"Location,Number of,Number of,Services departing within " << AnsiString(DepRange) << MinuteString <<
" with their departure times and exit codes\n";
17544 TTFile3 <<
",Platforms,Trains\n\n";
17546 Ptr1 = LocServiceTimesVector.begin();
17548 while(Ptr2 != LocServiceTimesVector.end())
17550 PreviousService =
"";
17551 NumTrainsAtLoc = 0;
17552 ServiceAndRepeatNumTotal =
"";
17554 NumPlatsAtThisLocCalculated =
false;
17556 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
17558 PreviousService =
"";
17559 NumTrainsAtLoc = 0;
17560 ServiceAndRepeatNumTotal =
"";
17562 NumPlatsAtThisLocCalculated =
false;
17566 if(Ptr2 == LocServiceTimesVector.end())
17571 if(Ptr2 == LocServiceTimesVector.end())
17575 while(Ptr2->Location == Ptr1->Location)
17577 PreviousService =
"";
17578 NumTrainsAtLoc = 0;
17579 ServiceAndRepeatNumTotal =
"";
17580 BasicTime = Ptr1->DepTime;
17581 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
17585 while(!
WithinTimeRange(3, BasicTime, Ptr2->DepTime, DepRange) || ((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
"")))
17587 BasicTime = Ptr2->DepTime;
17590 if(Ptr2 == LocServiceTimesVector.end())
17594 if(Ptr2->Location != Ptr1->Location)
17599 if(Ptr2 == LocServiceTimesVector.end())
17603 if(Ptr2->Location != Ptr1->Location)
17609 if((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
""))
17613 if(!NumPlatsAtThisLocCalculated)
17616 NumPlatsAtThisLocCalculated =
true;
17618 if(Ptr1->ServiceAndRepeatNum != PreviousService)
17620 if(ServiceAndRepeatNumTotal ==
"")
17622 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
17623 NumTrainsAtLoc = 1;
17627 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
17630 PreviousService = Ptr2->ServiceAndRepeatNum;
17631 if(ServiceAndRepeatNumTotal ==
"")
17633 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
17634 NumTrainsAtLoc = 1;
17638 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
17642 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(5, BasicTime, Ptr2->DepTime, DepRange)))
17644 int MaxNumberOfSameDirections = 0;
17645 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(3, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
false, AnalysisError, MaxNumberOfSameDirections);
17650 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
17654 AnsiString Asterisk =
"";
17655 if(MaxNumberOfSameDirections >= NumPlats)
17660 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
17661 DeparturesPrinted =
true;
17662 ServiceAndRepeatNumTotal =
"";
17664 if(Ptr2 == LocServiceTimesVector.end())
17668 if(Ptr2->Location != Ptr1->Location)
17673 if(Ptr2 == LocServiceTimesVector.end())
17679 if(!DeparturesPrinted)
17681 TTFile3 <<
"Nothing to report for departures";
17686 SequenceLog +=
"8\n";
17693 Ptr1 = LocServiceTimesVector.begin();
17695 while(Ptr2 != LocServiceTimesVector.end())
17697 while(Ptr2->Location == Ptr1->Location)
17700 if(Ptr2 == LocServiceTimesVector.end())
17707 if(Ptr2 != LocServiceTimesVector.end())
17714 TTFile3 <<
"Trains present at location analysis: an asterisk means that the number of trains at the location is greater than the number of platforms.\n\n";
17715 TTFile3 <<
"Location,Number of,Number of,Time,Services at the location at that time\n";
17716 TTFile3 <<
",Platforms,Trains,\n\n";
17717 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
17718 Ptr1 = LocServiceTimesVector.begin();
17720 while(Ptr2 != LocServiceTimesVector.end())
17722 PreviousService =
"";
17723 ServiceAndRepeatNumTotal =
"";
17724 NumTrainsAtLoc = 0;
17726 NumPlatsAtThisLocCalculated =
false;
17728 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
17730 PreviousService =
"";
17731 ServiceAndRepeatNumTotal =
"";
17732 NumTrainsAtLoc = 0;
17734 NumPlatsAtThisLocCalculated =
false;
17738 if(Ptr2 == LocServiceTimesVector.end())
17743 if(Ptr2 == LocServiceTimesVector.end())
17747 while(Ptr2->Location == Ptr1->Location)
17749 if(Ptr1->FrhMarker ==
"Frh")
17752 Ptr1->FrhMarker =
"FrhCounted";
17754 PreviousService =
"";
17755 NumTrainsAtLoc = 0;
17756 ServiceAndRepeatNumTotal =
"";
17757 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
17761 while((Ptr2->AtLocTime != Ptr1->AtLocTime) || ((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
"")))
17764 if(Ptr1->FrhMarker ==
"Frh")
17767 Ptr1->FrhMarker =
"FrhCounted";
17770 if(Ptr2 == LocServiceTimesVector.end())
17774 if(Ptr2->Location != Ptr1->Location)
17779 if(Ptr2 == LocServiceTimesVector.end())
17783 if(Ptr2->Location != Ptr1->Location)
17787 while(Ptr2->AtLocTime == Ptr1->AtLocTime)
17789 if((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
""))
17793 if(!NumPlatsAtThisLocCalculated)
17796 NumPlatsAtThisLocCalculated =
true;
17798 if(Ptr1->ServiceAndRepeatNum != PreviousService)
17800 if(ServiceAndRepeatNumTotal ==
"")
17802 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum;
17803 NumTrainsAtLoc = 1;
17807 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum;
17810 PreviousService = Ptr2->ServiceAndRepeatNum;
17811 if(ServiceAndRepeatNumTotal ==
"")
17813 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum;
17814 NumTrainsAtLoc = 1;
17818 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum;
17821 if(Ptr1->FrhMarker ==
"Frh")
17824 Ptr1->FrhMarker =
"FrhCounted";
17827 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (Ptr2->AtLocTime != Ptr1->AtLocTime))
17831 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTAtLoc(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc);
17833 if((NumTrainsAtLoc > 1) && ((FrhCount < NumTrainsAtLoc) || (FrhCount != LastFrhCount)))
17835 AnsiString Asterisk =
"";
17836 if(NumTrainsAtLoc > NumPlats)
17843 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
17845 else if(FrhCount == 1)
17847 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (1 remains here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
17851 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (" << FrhCount <<
" remain here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
17853 LastFrhCount = FrhCount;
17854 PreviousServiceAndRepeatNumTotalOutput = ServiceAndRepeatNumTotalOutput;
17855 AtLocsPrinted =
true;
17856 ServiceAndRepeatNumTotal =
"";
17859 if(Ptr2 == LocServiceTimesVector.end())
17863 if(Ptr2->Location != Ptr1->Location)
17868 if(Ptr2 == LocServiceTimesVector.end())
17876 TTFile3 <<
"Nothing to report for trains at locations";
17881 SequenceLog +=
"9\n";
17911 TTrainDataEntry SingleServiceEntry, PartServiceEntry, NewPartServiceEntry, TempEntry;
17916 TTFile3 <<
"Train direction analysis - consisting of train facing directions on creation and possible missing or questionable changes of direction:\n\n";
17917 for(
unsigned int x = 0; x < TrainDataVectorCopy.size(); x++)
17925 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
17927 SingleServiceEntry = TDE;
17929 for(
unsigned int y = 0; y < SSAV.size(); y++)
17931 if((SSAV.at(y).Command ==
"Fjo") || (SSAV.at(y).Command ==
"Frh") || (SSAV.at(y).Command ==
"Fer") || (SSAV.at(y).Command ==
"Frh-sh"))
17933 SingleServiceVector.push_back(SingleServiceEntry);
17936 else if((SSAV.at(y).Command ==
"fsp") || (SSAV.at(y).Command ==
"rsp"))
17938 PartServiceEntry = TDE;
17940 for(
unsigned int z = 0; z <= y; z++)
17945 PartServiceEntry.
ActionVector.at(z).Command =
"chr-sp";
17946 PartServiceEntry.
ActionVector.at(z).OtherHeadCode = PartServiceEntry.
ActionVector.at(z).LinkedTrainEntryPtr->ServiceReference;
17949 PartServiceVector.push_back(PartServiceEntry);
17950 if(SSAV.at(y).Command ==
"fsp")
17952 SSAV.at(y).Command =
"Front split - original service continues below";
17953 SSAV.at(y).OtherHeadCode =
"";
17955 if(SSAV.at(y).Command ==
"rsp")
17957 SSAV.at(y).Command =
"Rear split - original service continues below";
17958 SSAV.at(y).OtherHeadCode =
"";
17962 else if(SSAV.at(y).Command ==
"Fns")
17964 SSAV.at(y).Command =
"chr-Fns";
17965 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
17966 PartServiceVector.push_back(SingleServiceEntry);
17969 else if(SSAV.at(y).Command ==
"Fns-sh")
17971 SSAV.at(y).Command =
"chr-Fns-sh";
17972 SSAV.at(y).OtherHeadCode = SSAV.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
17973 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
17974 PartServiceVector.push_back(SingleServiceEntry);
17977 else if(SSAV.at(y).Command ==
"F-nshs")
17979 SSAV.at(y).Command =
"chr-F-nshs";
17980 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
17981 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
17982 PartServiceVector.push_back(SingleServiceEntry);
17988 SequenceLog +=
"10\n";
17992 AnsiString NextRef;
17993 while(!PartServiceVector.empty())
17995 PartServiceEntry = PartServiceVector.at(0);
17996 for(
unsigned int y = 0; y < PartServiceEntry.
ActionVector.size(); y++)
17998 if(PartServiceEntry.
ActionVector.at(y).Command.SubString(1,3) ==
"chr")
18000 NextRef = PartServiceEntry.
ActionVector.at(y).OtherHeadCode;
18004 bool FinishType =
true, FoundFlag =
false;
18011 for(
unsigned int y = 1; y < TempEntry.
ActionVector.size(); y++)
18015 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
18019 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
18025 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
18026 SingleServiceVector.push_back(PartServiceVector.at(0));
18027 PartServiceVector.erase(&PartServiceVector.at(0));
18032 NewPartServiceEntry = PartServiceVector.at(0);
18036 PartServiceVector.push_back(NewPartServiceEntry);
18039 TempEntry.
ActionVector.at(y).Command =
"Front split - original service continues below";
18044 TempEntry.
ActionVector.at(y).Command =
"Rear split - original service continues below";
18047 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
18049 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns")
18052 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
18054 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
18057 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns-sh")
18060 TempEntry.
ActionVector.at(y).OtherHeadCode = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
18061 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
18062 NextRef = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
18063 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
18066 else if(TempEntry.
ActionVector.at(y).Command ==
"F-nshs")
18070 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
18071 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
18072 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
18080 SequenceLog += +
"11\n";
18081 throw Exception(
"Unable to find service reference " + NextRef +
" Last ref checked = " + TempEntry.
ServiceReference);
18085 if(!PartServiceVector.empty())
18087 SequenceLog +=
"12\n";
18088 throw Exception(
"PartServiceVector should be empty here - size = " + PartServiceVector.size());
18090 SequenceLog +=
"13\n";
18135 bool BufferFacingUnReportedFlag =
true;
18136 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
18142 SequenceLog +=
"13a\n";
18143 throw Exception(
"Repeat entry present in SingleServiceVector at position " + x);
18146 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
18148 bool BufferFlag =
false;
18149 int FrontTVPos = AV.at(0).FrontStartOrRepeatDigits;
18150 int RearTVPos = AV.at(0).RearStartOrRepeatMins;
18151 AnsiString FrontLocName = AV.at(0).LocationName;
18152 int NextEntryPos, NextExitPos;
18155 if(ThisElement.
Conn[0] == RearTVPos)
18159 else if(ThisElement.
Conn[1] == RearTVPos)
18163 else if(ThisElement.
Conn[2] == RearTVPos)
18167 else if(ThisElement.
Conn[3] == RearTVPos)
18179 if(ThisElement.
Conn[ThisExitPos] == -1)
18181 SequenceLog =
"13b\n";
18182 throw Exception(
"ThisElement connects to -1 for " + TDE.
ServiceReference);
18185 NextEntryPos = ThisElement.
ConnLinkPos[ThisExitPos];
18186 if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 0) || (NextEntryPos == 2)))
18188 BufferFlag =
false;
18193 BufferFlag =
false;
18198 BufferFlag =
false;
18206 else if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 1) || (NextEntryPos == 3)))
18208 ThisElement = NextElement;
18214 if(NextEntryPos == 0)
18218 else if(NextEntryPos == 1)
18222 else if(NextEntryPos == 2)
18226 else if(NextEntryPos == 3)
18231 ThisElement = NextElement;
18232 ThisExitPos = NextExitPos;
18237 if(BufferFacingUnReportedFlag)
18239 TTFile3 <<
"Train facing direction on creation analysis:-\n\n";
18240 BufferFacingUnReportedFlag =
false;
18242 TTFile3 <<
"Service " + TDE.
ServiceReference +
" facing buffers on creation\n";
18246 if(BufferFacingUnReportedFlag)
18248 TTFile3 <<
"Nothing to report for train facing directions\n\n";
18254 SequenceLog +=
"13c\n";
18257 AnsiString LocationNameToBeChecked =
"";
18258 bool MissingcdtUnreportedFlag =
true;
18260 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
18263 unsigned int y = 0;
18264 int FirstInstance = 9999, SecondInstance = 9999;
18265 bool FullBreak =
false;
18266 MarkerList.clear();
18273 while((y < TDEntry.
ActionVector.size()) && !FullBreak)
18282 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
18284 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
18289 (AVEntry.
Command ==
"Frh-sh"))
18304 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
18310 if(TDEntry.
ActionVector.at(a).LocationName == LocationNameToBeChecked)
18312 SecondInstance = a;
18314 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
18316 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
18318 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
18321 if(MissingcdtUnreportedFlag)
18323 TTFile3 <<
"Possibly missing changes of direction - these will be missing unless the service travels in a loop back to the locations marked:-\n\n";
18325 TTFile3 << LocationNameToBeChecked <<
" is listed twice with no direction change between in service sequence: " << Sequence <<
"\n\n";
18326 MarkerList.push_back(FirstInstance);
18327 MarkerList.push_back(SecondInstance);
18329 MissingcdtUnreportedFlag =
false;
18340 if(MissingcdtUnreportedFlag)
18342 TTFile3 <<
"Nothing to report for missing changes of direction\n\n";
18348 SequenceLog +=
"14\n";
18357 typedef std::list<AnsiString> TLocList;
18358 TLocList BackwardList, ForwardList;
18359 bool IntroLineNeeded =
true;
18360 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
18362 unsigned int cdtPosition = 9999;
18363 AnsiString cdtLocation =
"";
18364 bool FoundSameName =
false;
18365 MarkerList.clear();
18367 for(
unsigned int y = 0; y < TDEntry.
ActionVector.size(); y++)
18370 BackwardList.clear();
18371 ForwardList.clear();
18375 (AVEntry.
Command ==
"Frh-sh"))
18377 if(MarkerList.empty())
18384 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
18386 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
18388 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
18392 if(IntroLineNeeded)
18394 TTFile3 <<
"Questionable change of direction analysis.\n\n";
18395 TTFile3 <<
"For marked changes of direction there are no same-name locations listed both above (up to the start or another direction change)\n";
18396 TTFile3 <<
"and below (down to the end or another direction change) but not counting the change of direction location itself.\n\n";
18397 TTFile3 <<
"These changes of direction are probably valid for movements to and from depots but all should be checked to\n";
18398 TTFile3 <<
"make sure that none has been included incorrectly:\n\n";
18399 IntroLineNeeded =
false;
18401 TTFile3 <<
"Service sequence " << Sequence <<
" contains questionable changes of direction:-\n\n";
18413 for(
int z = y - 1; z >= 0; z--)
18416 if(AVEntry2.
Command ==
"cdt")
18425 BackwardList.sort();
18426 BackwardList.unique();
18427 for(
unsigned int z = y + 1; z < TDEntry.
ActionVector.size(); z++)
18441 ForwardList.sort();
18442 ForwardList.unique();
18443 FoundSameName =
false;
18445 if(!BackwardList.empty() && !ForwardList.empty())
18447 for(TLocList::iterator BLIt = BackwardList.begin(); BLIt != BackwardList.end(); BLIt++)
18449 for(TLocList::iterator FLIt = ForwardList.begin(); FLIt != ForwardList.end(); FLIt++)
18453 FoundSameName =
true;
18460 MarkerList.push_back(cdtPosition);
18464 if(IntroLineNeeded)
18466 TTFile3 <<
"Nothing to report for questionable changes of direction\n\n";
18482 SequenceLog +=
"15\n";
18488 catch(
const Exception &e)
18490 AnsiString TTErrorFileName =
"Analysis Error.txt";
18491 TTErrorFileName = CurDir +
"\\Formatted timetables\\" + TTErrorFileName;
18492 std::ofstream TTError(TTErrorFileName.c_str());
18495 ShowMessage(
"Analysis error file failed to open - can't be created");
18499 AnsiString TimeNow = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
18500 TTError << TimeNow.c_str() <<
'\n' << ArrRange <<
'\n' << ArrChecked <<
'\n' << DepRange <<
'\n' <<
18501 DepChecked <<
'\n' << AtLocChecked <<
'\n' << SequenceLog <<
'\n' << AnsiString(e.Message);
18504 ShowMessage(
"Error in Conflict Analysis: A file called 'Analysis Error.txt' has been created in your Formatted timetables folder. Please send this file together with your railway and timetable files to railwayfeedback@gmail.com for investigation - many thanks");
18514 if((SSVectorNumber < 0) || ((
unsigned int)SSVectorNumber >= SingleServiceVector.size()))
18516 throw Exception(
"SSVectorNumber out of range, = " + AnsiString(SSVectorNumber) +
", Vector size = " + SingleServiceVector.size());
18518 TTrainDataEntry SingleService = SingleServiceVector.at(SSVectorNumber);
18520 VecFile <<
",Initial service reference " << SingleService.
ServiceReference +
'\n';
18521 AnsiString Marker =
"";
18522 for(
unsigned int x = 0; x < SingleService.
ActionVector.size(); x++)
18525 for(
TNumListIterator MLIt = MarkerList.begin(); MLIt != MarkerList.end(); MLIt++)
18527 if(
int(x) == *MLIt)
18538 VecFile << Marker << AnsiString(AVE.
EventTime.TimeString()) <<
' ' << AVE.
Command <<
' ' << RearID <<
' ' << FrontID <<
'\n';
18544 VecFile << Marker << AnsiString(AVE.
EventTime.TimeString()) <<
' ' << AVE.
Command <<
' ' << RearID <<
' ' << FrontID <<
' ' << AVE.
OtherHeadCode <<
'\n';
18557 if(AVE.
Command.SubString(1,3) ==
"chr")
18566 AVE.
Command =
"Change of service to ";
18568 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"Fns-sh")
18570 AVE.
Command =
"Change to shuttle finishing service";
18572 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"F-nshs")
18595 VecFile << Marker << AnsiString(AVE.
EventTime.TimeString()) <<
' ' <<
"Pass" <<
' ' << AVE.
LocationName <<
'\n';
18599 AnsiString ListOfExits =
"";
18604 VecFile << Marker << AnsiString(AVE.
EventTime.TimeString()) <<
" Fer " << ListOfExits <<
'\n';
18608 VecFile << Marker <<
"Frh" <<
'\n';
18623 for(
unsigned int x = 0; x < Vector.size(); x++)
18627 if(Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1).FormatType ==
Repeat)
18629 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 2);
18632 FinishType =
false;
18637 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1);
18640 FinishType =
false;
18645 return(Vector.at(x));
18649 return(Vector.at(Vector.size() - 1));
18658 if((Time1 ==
"") || (Time2 ==
""))
18663 int Mins = Time1.SubString(4,2).ToInt();
18664 int Hours = Time1.SubString(1,2).ToInt();
18665 int Time1Mins = (Hours * 60) + Mins;
18666 Mins = Time2.SubString(4,2).ToInt();
18667 Hours = Time2.SubString(1,2).ToInt();
18668 int Time2Mins = (Hours * 60) + Mins;
18669 if(abs(Time1Mins - Time2Mins) <= MinuteRange)
18681 bool &AnalysisError,
int &MaxNumberOfSameDirections)
18688 AnsiString Output =
"", OneService =
"", TempStr1 =
"", TempStr2 =
"";
18690 std::list<AnsiString> ServiceList;
18692 bool EvenComma =
false;
18693 for(
int x = 1; x <= Input.Length(); x++)
18695 TempStr1 = Input[x];
18696 if(TempStr1 == AnsiString(
',') && EvenComma)
18702 TempStr2 += Input[x];
18704 if(TempStr1 == AnsiString(
','))
18706 EvenComma = !EvenComma;
18710 while(TempStr2.Length() > 0)
18712 SCPos = TempStr2.Pos(
';');
18715 OneService = TempStr2.SubString(1, SCPos - 1);
18716 ServiceList.push_back(OneService);
18717 TempStr2 = TempStr2.SubString(SCPos + 1, TempStr2.Length() - SCPos);
18721 ServiceList.push_back(TempStr2);
18725 ServiceList.sort();
18726 ServiceList.unique();
18727 NumTrainsAtLoc = ServiceList.size();
18730 int DirectionMarker = 0;
18732 std::list<AnsiString>::iterator SLIt, SLIt1, SLIt2, SLIt3;
18734 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
18736 *SLIt = *SLIt +
"&0";
18738 SLIt3 = ServiceList.end();
18740 AnsiString ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatInfo1, RepeatInfo2;
18741 int AmpersandPos, SpacePos, CommaPos1, CommaPos2, RepeatNum1, RepeatNum2;
18742 TAllServiceCallingLocsMap::iterator ASCLIt1, ASCLIt2;
18744 MaxNumberOfSameDirections = 0;
18745 int SameDirectionCount = 0;
18747 for(std::list<AnsiString>::iterator SLIt1 = ServiceList.begin(); SLIt1 != SLIt3; SLIt1++)
18751 if(SLIt1->SubString(SLIt1->Length() - 1, 2) != AnsiString(
"&0"))
18757 CommaPos1 = SLIt1->Pos(
',');
18758 ServiceRef1 = SLIt1->SubString(1, CommaPos1 - 1);
18760 SpacePos = ServiceRef1.Pos(
' ');
18764 RepeatInfo1 = ServiceRef1.SubString(SpacePos + 2, ServiceRef1.Length() - SpacePos - 2);
18765 ServiceRef1 = ServiceRef1.SubString(1, SpacePos - 1);
18766 if(RepeatInfo1[1] ==
'F')
18772 SpacePos = RepeatInfo1.Pos(
' ');
18773 RepeatNum1 = RepeatInfo1.SubString(SpacePos + 1, RepeatInfo1.Length() - SpacePos).ToInt();
18776 AnsiTime1 = SLIt1->SubString(CommaPos1 + 1, SLIt1->Length() - CommaPos1);
18778 AmpersandPos = AnsiTime1.Pos(
'&');
18779 AnsiTime1 = AnsiTime1.SubString(1, AmpersandPos - 1);
18784 throw Exception(
"ASCLIt1 Error in " + Input);
18786 ServiceCallingLocsList1 = ASCLIt1->second;
18787 AmpersandPos = SLIt1->Pos(
'&');
18788 *SLIt1 = SLIt1->SubString(1, AmpersandPos);
18789 *SLIt1 = *SLIt1 + AnsiString(++DirectionMarker);
18791 SameDirectionCount = 1;
18792 for(SLIt2 = SLIt; SLIt2 != ServiceList.end(); SLIt2++)
18794 CommaPos2 = SLIt2->Pos(
',');
18795 ServiceRef2 = SLIt2->SubString(1, CommaPos2 - 1);
18797 SpacePos = ServiceRef2.Pos(
' ');
18801 RepeatInfo2 = ServiceRef2.SubString(SpacePos + 2, ServiceRef2.Length() - SpacePos - 2);
18802 ServiceRef2 = ServiceRef2.SubString(1, SpacePos - 1);
18803 if(RepeatInfo2[1] ==
'F')
18809 SpacePos = RepeatInfo2.Pos(
' ');
18810 RepeatNum2 = RepeatInfo2.SubString(SpacePos + 1, RepeatInfo2.Length() - SpacePos).ToInt();
18813 AnsiTime2 = SLIt2->SubString(CommaPos2 + 1, SLIt2->Length() - CommaPos2);
18815 AmpersandPos = AnsiTime2.Pos(
'&');
18816 AnsiTime2 = AnsiTime2.SubString(1, AmpersandPos - 1);
18821 throw Exception(
"ASCLIt2 Error in " + Input);
18823 ServiceCallingLocsList2 = ASCLIt2->second;
18825 if(
SameDirection(0, ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatNum1, RepeatNum2, ServiceCallingLocsList1, ServiceCallingLocsList2, Location, Arrival))
18827 int AmpersandPos = SLIt2->Pos(
'&');
18828 *SLIt2 = SLIt2->SubString(1, AmpersandPos);
18829 *SLIt2 = *SLIt2 + AnsiString(DirectionMarker);
18830 SameDirectionCount++;
18833 if(SameDirectionCount > MaxNumberOfSameDirections)
18835 MaxNumberOfSameDirections = SameDirectionCount;
18840 if(SLIt3->SubString(SLIt3->Length() - 1, 2) == AnsiString(
"&0"))
18843 AmpersandPos = SLIt3->Pos(
'&');
18844 *SLIt3 = SLIt3->SubString(1, AmpersandPos);
18845 *SLIt3 = *SLIt3 + AnsiString(++DirectionMarker);
18848 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
18851 AmpersandPos = SLIt->Pos(
'&');
18852 AnsiString DirectionMarkerString = SLIt->SubString(AmpersandPos + 1, SLIt->Length() - AmpersandPos);
18853 AnsiString ServiceWithoutMarker = SLIt->SubString(1, AmpersandPos - 1);
18854 DirectionMarker = DirectionMarkerString.ToInt();
18855 AnsiString DirectionSuffix =
"";
18857 if(DirectionMarker < 27)
18859 c = 64 + DirectionMarker;
18860 DirectionSuffix =
"," + AnsiString(c);
18862 else if(DirectionMarker < 53)
18864 c = 65 + DirectionMarker - 27;
18865 DirectionSuffix =
",A" + AnsiString(c);
18869 DirectionSuffix =
",?";
18871 *SLIt = ServiceWithoutMarker + DirectionSuffix;
18874 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
18876 Output = Output + *SLIt +
",";
18878 if(Output.Length() > 0)
18880 Output = Output.SubString(1, Output.Length() - 1);
18886 catch(
const Exception &e)
18888 AnalysisError =
true;
18900 AnsiString InternalInput = Input, Output =
"", OneService =
"";
18902 std::list<AnsiString> ServiceList;
18904 while(InternalInput.Length() > 0)
18906 CommaPos = InternalInput.Pos(
',');
18909 OneService = InternalInput.SubString(1, CommaPos - 1);
18910 ServiceList.push_back(OneService);
18911 InternalInput = InternalInput.SubString(CommaPos + 1, InternalInput.Length() - CommaPos);
18915 ServiceList.push_back(InternalInput);
18916 InternalInput =
"";
18920 ServiceList.sort();
18921 ServiceList.unique();
18922 NumTrainsAtLoc = ServiceList.size();
18923 for(std::list<AnsiString>::iterator SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
18925 Output = Output + *SLIt +
",";
18927 if(Output.Length() > 0)
18929 Output = Output.SubString(1, Output.Length() - 1);
18942 AnsiString(RepeatNum1) +
"," + AnsiString(RepeatNum2) +
"," + Location);
18944 std::list<AnsiString>::iterator LP1 = 0, LP2 = 0, ListPtr1 = 0, ListPtr2 = 0, LocPtr1 = 0, LocPtr2 = 0;
18949 bool LocFound =
false;
18950 AnsiString Ref1 = Ref1In, Ref2 = Ref2In;
18952 TDateTime FirstServiceTime;
18955 int Ref1Target = 0, Ref1Count = 0;
18956 int SlashPos = Ref1.Pos(
'/');
18959 Ref1Target = Ref1.SubString(SlashPos + 1, Ref1.Length() - SlashPos).ToInt();
18960 Ref1 = Ref1.SubString(1, SlashPos - 1);
18962 int Ref2Target = 0, Ref2Count = 0;
18963 SlashPos = Ref2.Pos(
'/');
18966 Ref2Target = Ref2.SubString(SlashPos + 1, Ref2.Length() - SlashPos).ToInt();
18967 Ref2 = Ref2.SubString(1, SlashPos - 1);
18969 for(ListPtr1 = List1.begin(); ListPtr1 != List1.end(); ListPtr1++)
18972 if((*ListPtr1) == Location)
18974 LocPtr1 = ListPtr1;
18977 if(ListPtr1->SubString(1, 3) ==
"%%%")
18979 AnsiString CDTTime = ListPtr1->SubString(4, 5);
18984 FirstServiceTime = TDateTime(-1);
18985 bool BreakFlag =
false;
18988 if(TDVIt->ServiceReference == Ref1)
18990 if(Ref1Target > Ref1Count)
18995 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
18996 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
19000 FirstServiceTime = AVIt->EventTime;
19006 FirstServiceTime = AVIt->ArrivalTime;
19012 FirstServiceTime = AVIt->DepartureTime;
19023 if(IncMinutes == -1)
19025 throw Exception(
"Failed to find service for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
19027 if(FirstServiceTime == TDateTime(-1))
19029 throw Exception(
"Failed to find first service time for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
19033 if(!Arrival && (Time1 == CDTTime))
19038 if(Arrival && (Time1 == CDTTime))
19042 if(Time1 > CDTTime)
19047 if(Time1 < CDTTime)
19060 for(ListPtr2 = List2.begin(); ListPtr2 != List2.end(); ListPtr2++)
19062 if((*ListPtr2) == Location)
19064 LocPtr2 = ListPtr2;
19067 if(ListPtr2->SubString(1, 3) ==
"%%%")
19069 AnsiString CDTTime = ListPtr2->SubString(4, 5);
19074 FirstServiceTime = TDateTime(-1);
19075 bool BreakFlag =
false;
19078 if(TDVIt->ServiceReference == Ref2)
19080 if(Ref2Target > Ref2Count)
19085 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
19086 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
19090 FirstServiceTime = AVIt->EventTime;
19096 FirstServiceTime = AVIt->ArrivalTime;
19102 FirstServiceTime = AVIt->DepartureTime;
19113 if(IncMinutes == -1)
19115 throw Exception(
"IncMinutes -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
19117 if(FirstServiceTime == TDateTime(-1))
19119 throw Exception(
"First service time -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
19123 if(!Arrival && (Time2 == CDTTime))
19128 if(Arrival && (Time2 == CDTTime))
19132 if(Time2 > CDTTime)
19137 if(Time2 < CDTTime)
19152 LP1 = List1.begin();
19154 for(ListPtr1 = LocPtr1; ListPtr1 != LP1; ListPtr1--)
19156 if(ListPtr1 == List1.begin())
19160 if(ListPtr1->SubString(1, 3) ==
"%%%")
19167 LP2 = List2.begin();
19169 for(ListPtr2 = LocPtr2; ListPtr2 != LP2; ListPtr2--)
19171 if(ListPtr2 == List2.begin())
19175 if(ListPtr2->SubString(1, 3) ==
"%%%")
19185 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
19187 if(ListPtr1 == LocPtr1)
19191 if(ListPtr1->SubString(1, 3) ==
"%%%")
19195 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
19197 if(ListPtr2 == LocPtr2)
19201 if(ListPtr2->SubString(1, 3) ==
"%%%")
19205 if((*ListPtr1) == (*ListPtr2))
19222 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
19224 if(ListPtr1 == List1.end())
19228 if(ListPtr1->SubString(1, 3) ==
"%%%")
19232 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
19234 if(ListPtr2 == List2.end())
19238 if(ListPtr2->SubString(1, 3) ==
"%%%")
19242 if((*ListPtr1) == (*ListPtr2))
19259 if(ExitList.empty())
19265 AnsiString ExitLocList =
"";
19268 unsigned int Counter = 0;
19269 for(
TNumListIterator ELIt = ExitList.begin(); ELIt != ExitList.end(); ELIt++)
19273 if(((Counter % 6) == 0) && (Counter < (ExitList.size() - 1)))
19275 ExitLocList +=
"\n";
19278 if(StartName ==
"")
19280 if(ExitList.size() == 1)
19284 return(
" at " + ID);
19289 if(ExitList.size() < 4)
19291 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
19296 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
19301 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
19306 if(ExitList.size() < 4)
19308 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
19313 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
19319 if(ExitList.size() < 4)
19321 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
19322 return(
" at " + StartName);
19326 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
19327 return(
" at " + StartName);
19367 AnsiString FormatStr =
"####0.0";
19368 AnsiString AvLateArrMins =
"";
19369 AnsiString AvEarlyArrMins =
"";
19370 AnsiString AvLatePassMins =
"";
19371 AnsiString AvEarlyPassMins =
"";
19372 AnsiString AvLateDepMins =
"";
19373 AnsiString AvLateExitMins =
"";
19374 AnsiString AvEarlyExitMins =
"";
19377 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
19410 PerfFile <<
'\n' <<
'\n' <<
"***************************************";
19411 PerfFile <<
'\n' <<
'\n' <<
"Performance summary:" <<
'\n';
19423 PerfFile <<
LateArrivals <<
" late arrivals (average " << AvLateArrMins.c_str() <<
" min)" <<
'\n';
19427 PerfFile <<
LateArrivals <<
" late arrival (" << AvLateArrMins.c_str() <<
" min)" <<
'\n';
19435 PerfFile <<
EarlyArrivals <<
" early arrivals (average " << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
19439 PerfFile <<
EarlyArrivals <<
" early arrival (" << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
19447 PerfFile <<
OnTimePasses <<
" on-time passes" <<
'\n';
19455 PerfFile <<
LatePasses <<
" late passes (average " << AvLatePassMins.c_str() <<
" min)" <<
'\n';
19459 PerfFile <<
LatePasses <<
" late pass (" << AvLatePassMins.c_str() <<
" min)" <<
'\n';
19463 PerfFile <<
LatePasses <<
" late passes" <<
'\n';
19467 PerfFile <<
EarlyPasses <<
" early passes (average " << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
19471 PerfFile <<
EarlyPasses <<
" early pass (" << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
19475 PerfFile <<
EarlyPasses <<
" early passes" <<
'\n';
19480 PerfFile <<
OnTimeExits <<
" on-time exits" <<
'\n';
19484 PerfFile <<
OnTimeExits <<
" on-time exit" <<
'\n';
19488 PerfFile <<
LateExits <<
" late exits (average " << AvLateExitMins.c_str() <<
" min)" <<
'\n';
19492 PerfFile <<
LateExits <<
" late exit (" << AvLateExitMins.c_str() <<
" min)" <<
'\n';
19496 PerfFile <<
LateExits <<
" late exits" <<
'\n';
19500 PerfFile <<
EarlyExits <<
" early exits (average " << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
19504 PerfFile <<
EarlyExits <<
" early exit (" << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
19508 PerfFile <<
EarlyExits <<
" early exits" <<
'\n';
19513 PerfFile <<
OnTimeDeps <<
" on-time departures" <<
'\n';
19517 PerfFile <<
OnTimeDeps <<
" on-time departure" <<
'\n';
19521 PerfFile <<
LateDeps <<
" late departures (average " << AvLateDepMins.c_str() <<
" min)" <<
'\n';
19525 PerfFile <<
LateDeps <<
" late departure (" << AvLateDepMins.c_str() <<
" min)" <<
'\n';
19529 PerfFile <<
LateDeps <<
" late departures" <<
'\n';
19531 TDateTime TempExcessLCDownTime;
19545 if(TempExcessLCDownTime > TDateTime(0))
19551 AnsiString FormattedExcessLCDownMins = FormatFloat(FormatStr,
ExcessLCDownMins);
19555 PerfFile << FormattedExcessLCDownMins.c_str() <<
" excess minutes of level crossing barrier down time" <<
'\n';
19563 PerfFile <<
MissedStops <<
" missed stops" <<
'\n';
19567 PerfFile <<
MissedStops <<
" missed stop" <<
'\n';
19603 PerfFile <<
NumFailures <<
" train failures" <<
'\n';
19607 PerfFile <<
NumFailures <<
" train failure" <<
'\n';
19613 PerfFile <<
AvHoursIntValue <<
" hour mean time betweeen train failures" <<
'\n';
19617 PerfFile <<
AvHoursIntValue <<
" hours mean time betweeen train failures" <<
'\n';
19620 AnsiString AvLateMinsLocsNotReached =
"";
19626 if(LocsNotReached > 0)
19629 PerfFile << LocsNotReached <<
" locations that trains failed to reach (average lateness " << AvLateMinsLocsNotReached.c_str() <<
" min)" <<
'\n';
19633 PerfFile <<
SPADRisks <<
" SPAD risks" <<
'\n';
19637 PerfFile <<
SPADRisks <<
" SPAD risk" <<
'\n';
19649 PerfFile <<
Derailments <<
" derailments" <<
'\n';
19653 PerfFile <<
Derailments <<
" derailment" <<
'\n';
19663 PerfFile <<
'\n' <<
"***************************************" <<
'\n';
19665 bool DerailSPADFlag =
false, CrashFlag =
false;
19667 int OverallScorePercent = 100;
19668 int TotArrDepExit = 0;
19669 double TotLateMinsFactor = 1;
19670 double MissedStopAndSPADRiskFactor = 1;
19671 double NetNegFactor = 1;
19681 OverallScorePercent = 5;
19682 DerailSPADFlag =
true;
19686 OverallScorePercent = 0;
19689 if(OverallScorePercent == 100)
19694 LatenessPenalty = 0;
19700 if(TotArrDepExit > 0)
19709 NetNegFactor = TotLateMinsFactor * MissedStopAndSPADRiskFactor;
19711 OverallScorePercent = 100 * NetNegFactor;
19714 if((TotArrDepExit > 0) || DerailSPADFlag || CrashFlag)
19717 AnsiString OneFailureString =
", though the failure would account for some poor performance";
19718 AnsiString TwoOrMoreFailureString =
", though the failures would account for some poor performance";
19719 AnsiString AddedString =
"";
19722 AddedString = OneFailureString;
19726 AddedString = TwoOrMoreFailureString;
19728 PerfFile <<
"\nOverall score: " << OverallScorePercent <<
"%\n";
19729 AnsiString Rating =
"";
19730 if(OverallScorePercent == 100)
19732 Rating =
"Perfect!";
19734 else if(OverallScorePercent >= 95)
19736 Rating =
"Excellent";
19738 else if(OverallScorePercent >= 90)
19740 Rating =
"Very good";
19742 else if(OverallScorePercent >= 80)
19746 else if(OverallScorePercent >= 70)
19750 else if(OverallScorePercent >= 60)
19752 Rating =
"Unacceptable" + AddedString;
19754 else if(OverallScorePercent >= 50)
19756 Rating =
"Poor" + AddedString;
19758 else if(OverallScorePercent >= 40)
19760 Rating =
"Bad" + AddedString;
19762 else if(OverallScorePercent >= 30)
19764 Rating =
"Very bad" + AddedString;
19766 else if(OverallScorePercent >= 20)
19768 Rating =
"Terrible" + AddedString;
19770 else if(OverallScorePercent >= 10)
19772 Rating =
"Appalling" + AddedString;
19774 else if(OverallScorePercent >= 5)
19778 Rating =
"Disastrous - potential loss of life";
19783 Rating =
"Dire" + AddedString;
19786 else if(OverallScorePercent < 5)
19790 Rating =
"Catastrophic - loss of life";
19794 Rating =
"Abysmal";
19797 PerfFile <<
"Overall rating: " << Rating.c_str() <<
'\n';
19801 PerfFile <<
"\nThere were no timetabled departures, arrivals or exits so there is insufficient information to provide a performance score or rating" <<
'\n';
19803 PerfFile <<
'\n' <<
"***************************************";
19813 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
19863 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
19898 int IncrementalMinutes = 0;
19912 bool TrainOperatingFlag =
false;
19917 TrainOperatingFlag =
true;
19921 if(TrainOperatingFlag)
19929 for(
unsigned int z = 0; z < TDEntry.
ActionVector.size(); z++)
19976 AnsiString HeadCode;
19980 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
19984 HCandTrainPosParam.first = HeadCode;
19985 HCandTrainPosParam.second = TrainID;
19987 if((TimeToAct >= 0) && (TimeToAct < 59.9))
19990 OpTimeToActMultiMapEntry.first = TimeToAct;
19991 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
20020 float TimeToAct = 0;
20021 int DistanceToRedSignal = 0;
20024 ContinuationEntryVecPosVector.clear();
20025 bool LaterTrain =
false;
20029 LaterTrain =
false;
20030 if(CTEIt->second.TrainDataEntryPtr->TrainOperatingDataVector.at(CTEIt->second.RepeatNumber).RunningEntry !=
NotStarted)
20041 if(!ContinuationEntryVecPosVector.empty())
20043 for(
unsigned int x = 0; x < ContinuationEntryVecPosVector.size(); x++)
20045 if(CTEIt->second.VectorPosition == ContinuationEntryVecPosVector.at(x))
20059 ContinuationEntryVecPosVector.push_back(CTEIt->second.VectorPosition);
20060 AnsiString HeadCode = CTEIt->second.HeadCode;
20061 float CurrentStopTime;
20062 float LaterStopTime;
20063 float RecoverableTime;
20066 int DistanceToExit;
20068 bool SigControlAndCanPassRedSignal =
false;
20076 if(CTEIt->second.TrainDataEntryPtr->ActionVector.size() == 1)
20082 SigControlAndCanPassRedSignal, &CTEIt->second.TrainDataEntryPtr->ActionVector.at(AtValue),
20083 HeadCode, TrainID, CurrentStopTime, LaterStopTime, RecoverableTime, AvTrackSpeed, DistanceToExit, ExitPair);
20086 if(AvTrackSpeed < 30)
20090 if(DistanceToRedSignal == -1)
20096 int Speed = AvTrackSpeed;
20097 int MaxSpeed = int(CTEIt->second.TrainDataEntryPtr->MaxRunningSpeed);
20098 if(AvTrackSpeed > MaxSpeed)
20102 if(CTEIt->second.TrainDataEntryPtr->ActionVector.at(0).SignallerControl)
20105 Speed = CTEIt->second.TrainDataEntryPtr->SignallerSpeed;
20108 TimeToAct = LaterStopTime + DistanceToRedSignal * 3.6 / 60 / Speed;
20113 float MinsBefEnter = double(CTEIt->first -
TTClockTime) * 86400.0 / 60.0;
20114 TimeToAct += MinsBefEnter;
20117 HCandTrainPosParam.first = HeadCode;
20118 HCandTrainPosParam.second = -1 - CTEIt->second.VectorPosition;
20121 if(TimeToAct < 59.9)
20123 OpTimeToActMultiMapEntry.first = TimeToAct;
20124 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
20149 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
20159 TimeToExitMultiMapEntry.first = ExitPair;
20160 TimeToExitMultiMapEntry.second = ExitInfo;
20170 bool SigControlAndCanPassRedSignal,
TActionVectorEntry *AVPtr, AnsiString HeadCode,
int TrainID,
float &CurrentStopTime,
float &LaterStopTime,
20171 float &RecoverableTime,
int &AvTrackSpeed,
int &DistanceToExit,
THVShortPair &ExitPair)
20180 AnsiString(TrackVectorPositionEntryPos) +
", " + AVPtr->
Command);
20181 int DistanceToRedSignal = 0;
20182 DistanceToExit = -1;
20183 ExitPair.first = -1;
20184 ExitPair.second = -1;
20185 int CumTrackSpeed = 0;
20187 int TrackSpeedCount = 0;
20188 float KmPerLocationStop;
20189 float MaxAllowableSpeed;
20199 int CurrentElement = TrackVectorPosition;
20200 int CurrentEntryPos = TrackVectorPositionEntryPos;
20205 CurrentStopTime = 0;
20207 RecoverableTime = 0;
20208 if(CurrentElement == -1)
20213 int CurrentExitPos;
20218 if((CurrentEntryPos == 0) || (CurrentEntryPos == 2))
20222 CurrentExitPos = 1;
20226 CurrentExitPos = 3;
20231 CurrentExitPos = 0;
20267 CurrentStopTime = float(TimeToDepart);
20273 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
20284 else if(SigControlAndCanPassRedSignal)
20289 if((NextEntryPos == 0) || (NextEntryPos == 2))
20310 CurrentElement = NextElement;
20311 CurrentEntryPos = NextEntryPos;
20312 CurrentExitPos = NextExitPos;
20324 int LaterStopNumber = 0;
20328 while(!((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0)))
20337 if(CurrentEntryPos > 1)
20352 DistanceToExit = DistanceToRedSignal;
20357 if(TrackSpeedCount > 0)
20359 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
20363 if(CurrentEntryPos > 1)
20374 if(LaterStopNumber > 0)
20376 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
20377 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
20383 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
20387 if(AvTrackSpeed > MaxAllowableSpeed)
20389 AvTrackSpeed = MaxAllowableSpeed;
20401 bool StopRequired =
false;
20418 int TrainOnElement;
20425 if(CurrentEntryPos > 1)
20434 if((TrainOnElement > -1) && (TrainOnElement != TrainID))
20443 double StopTimeDouble;
20456 if(StopTimeDouble < 0.5)
20458 StopTimeDouble = 0.5;
20462 LaterStopTime += float(StopTimeDouble);
20463 RecoverableTime += StopTimeDouble - 0.5;
20464 if((LaterStopNumber == 1) && (TrainID > -1))
20472 if((AVPtr + 1)->FormatType ==
TimeLoc)
20476 StopTimeDouble = double((AVPtr + 1)->DepartureTime - AVPtr->
ArrivalTime) * 86400.0 / 60.0;
20478 if(StopTimeDouble < 0.5)
20480 StopTimeDouble = 0.5;
20483 LaterStopTime += float(StopTimeDouble);
20484 RecoverableTime += StopTimeDouble - 0.5;
20485 if((LaterStopNumber == 1) && (TrainID > -1))
20501 if(NextElement == -1)
20510 if((NextEntryPos == 0) || (NextEntryPos == 2))
20531 CurrentElement = NextElement;
20532 CurrentEntryPos = NextEntryPos;
20533 CurrentExitPos = NextExitPos;
20537 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
20550 if(TrackSpeedCount > 0)
20552 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
20556 if(CurrentEntryPos > 1)
20567 if(LaterStopNumber > 0)
20569 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
20570 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
20576 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
20580 if(AvTrackSpeed > MaxAllowableSpeed)
20582 AvTrackSpeed = MaxAllowableSpeed;
20585 return(DistanceToRedSignal);